Skip to content

Commit

Permalink
check repeated salt after first successful decryption
Browse files Browse the repository at this point in the history
fixes #442
  • Loading branch information
zonyitoo committed Mar 5, 2021
1 parent 22e2640 commit a021cc4
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 39 deletions.
82 changes: 82 additions & 0 deletions configs/iptables_mixed.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/bin/sh

if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root" 1>&2
exit 1
fi

## TCP
# NAT PREROUTING
iptables -t nat -N shadowsocks-nat
# Skip LoopBack, Reserved
iptables -t nat -A shadowsocks-nat -d 0/8 -j RETURN
iptables -t nat -A shadowsocks-nat -d 127/8 -j RETURN
iptables -t nat -A shadowsocks-nat -d 10/8 -j RETURN
iptables -t nat -A shadowsocks-nat -d 169.254/16 -j RETURN
iptables -t nat -A shadowsocks-nat -d 172.16/12 -j RETURN
iptables -t nat -A shadowsocks-nat -d 192.168/16 -j RETURN
iptables -t nat -A shadowsocks-nat -d 224/4 -j RETURN
iptables -t nat -A shadowsocks-nat -d 240/4 -j RETURN
# Bypass CN IPs
iptables -t nat -A shadowsocks-nat -m set --match-set cn dst -j RETURN
# Bypass sslocal's outbound data
iptables -t nat -A shadowsocks-nat -m mark --mark 255 -j RETURN
# Redirect TCP to 60080
iptables -t nat -A shadowsocks-nat -p tcp -j REDIRECT --to-ports 60080
# Local TCP -> shadowsocks-nat
iptables -t nat -A OUTPUT -p tcp -j shadowsocks-nat
# LAN TCP -> shadowsocks-nat
iptables -t nat -A PREROUTING -p tcp -j shadowsocks-nat

## UDP
# Strategy Route
ip rule add fwmark 1 table 233
ip route add local 0.0.0.0/0 dev lo table 233

# TPROXY for LAN
iptables -t mangle -N shadowsocks-tproxy
# Skip LoopBack, Reserved
iptables -t mangle -A shadowsocks-tproxy -d 0/8 -j RETURN
iptables -t mangle -A shadowsocks-tproxy -d 127/8 -j RETURN
iptables -t mangle -A shadowsocks-tproxy -d 10/8 -j RETURN
iptables -t mangle -A shadowsocks-tproxy -d 169.254/16 -j RETURN
iptables -t mangle -A shadowsocks-tproxy -d 172.16/12 -j RETURN
iptables -t mangle -A shadowsocks-tproxy -d 192.168/16 -j RETURN
iptables -t mangle -A shadowsocks-tproxy -d 224/4 -j RETURN
iptables -t mangle -A shadowsocks-tproxy -d 240/4 -j RETURN
# Bypass CN IPs
iptables -t mangle -A shadowsocks-tproxy -m set --match-set cn dst -j RETURN
# Bypass sslocal's outbound data
iptables -t mangle -A shadowsocks-tproxy -m mark --mark 255 -j RETURN
# TPROXY UDP to 60080
iptables -t mangle -A shadowsocks-tproxy -p udp -j TPROXY --on-port 60080 --tproxy-mark 1/1
#iptables -t mangle -A shadowsocks-tproxy -p tcp -j TPROXY --on-port 60080 --tproxy-mark 1/1
# Apply TPROXY to LAN
iptables -t mangle -A PREROUTING -p udp -j shadowsocks-tproxy

# TPROXY for Local
iptables -t mangle -N shadowsocks-tproxy-mark
# Skip LoopBack, Reserved
iptables -t mangle -A shadowsocks-tproxy-mark -d 127/8 -j RETURN
iptables -t mangle -A shadowsocks-tproxy-mark -d 10/8 -j RETURN
iptables -t mangle -A shadowsocks-tproxy-mark -d 169.254/16 -j RETURN
iptables -t mangle -A shadowsocks-tproxy-mark -d 172.16/12 -j RETURN
iptables -t mangle -A shadowsocks-tproxy-mark -d 192.168/16 -j RETURN
iptables -t mangle -A shadowsocks-tproxy-mark -d 224/4 -j RETURN
iptables -t mangle -A shadowsocks-tproxy-mark -d 240/4 -j RETURN
# Bypass CN IPs
iptables -t mangle -A shadowsocks-tproxy-mark -m set --match-set cn dst -j RETURN
# Bypass sslocal's outbound data
iptables -t mangle -A shadowsocks-tproxy-mark -m mark --mark 255 -j RETURN
# Set MARK and reroute
iptables -t mangle -A shadowsocks-tproxy-mark -p udp -j MARK --set-xmark 1
#iptables -t mangle -A shadowsocks-tproxy-mark -p tcp -j MARK --set-xmark 1
# Apply TPROXY for Local
iptables -t mangle -A OUTPUT -p udp -j shadowsocks-tproxy-mark

# DIVERT rules
# For optimizing TCP
# iptables -t mangle -N shadowsocks-divert
# iptables -t mangle -A shadowsocks-divert -j MARK --set-mark 1
# iptables -t mangle -A shadowsocks-divert -j ACCEPT
# iptables -t mangle -I PREROUTING -p tcp -m socket -j shadowsocks-divert
42 changes: 21 additions & 21 deletions configs/iptables_tproxy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,31 +37,31 @@ iptables -t mangle -A PREROUTING -j SS
#ip6tables -t mangle -A PREROUTING -j SS

# OUTPUT rules
iptables -t mangle -N SS-MASK
#ip6tables -t mangle -N SS-MASK
iptables -t mangle -N SS-MARK
#ip6tables -t mangle -N SS-MARK
# Reserved addresses
iptables -t mangle -A SS-MASK -d 0/8 -j RETURN
iptables -t mangle -A SS-MASK -d 127/8 -j RETURN
iptables -t mangle -A SS-MASK -d 10/8 -j RETURN
iptables -t mangle -A SS-MASK -d 169.254/16 -j RETURN
iptables -t mangle -A SS-MASK -d 172.16/12 -j RETURN
iptables -t mangle -A SS-MASK -d 192.168/16 -j RETURN
iptables -t mangle -A SS-MASK -d 224/4 -j RETURN
iptables -t mangle -A SS-MASK -d 240/4 -j RETURN
#ip6tables -t mangle -A SS-MASK -d ::1/128 -j RETURN
#ip6tables -t mangle -A SS-MASK -d fc00::/7 -j RETURN
#ip6tables -t mangle -A SS-MASK -d fe80::/10 -j RETURN
iptables -t mangle -A SS-MARK -d 0/8 -j RETURN
iptables -t mangle -A SS-MARK -d 127/8 -j RETURN
iptables -t mangle -A SS-MARK -d 10/8 -j RETURN
iptables -t mangle -A SS-MARK -d 169.254/16 -j RETURN
iptables -t mangle -A SS-MARK -d 172.16/12 -j RETURN
iptables -t mangle -A SS-MARK -d 192.168/16 -j RETURN
iptables -t mangle -A SS-MARK -d 224/4 -j RETURN
iptables -t mangle -A SS-MARK -d 240/4 -j RETURN
#ip6tables -t mangle -A SS-MARK -d ::1/128 -j RETURN
#ip6tables -t mangle -A SS-MARK -d fc00::/7 -j RETURN
#ip6tables -t mangle -A SS-MARK -d fe80::/10 -j RETURN

# Bypass sslocal with mask 0xff (255)
iptables -t mangle -A SS-MASK -j RETURN -m mark --mark 0xff
#ip6tables -t mangle -A SS-MASK -j RETURN -m mark --mark 0xff
iptables -t mangle -A SS-MARK -j RETURN -m mark --mark 0xff
#ip6tables -t mangle -A SS-MARK -j RETURN -m mark --mark 0xff

# Reroute
iptables -t mangle -A SS-MASK -p udp -j MARK --set-mark 0x2333
iptables -t mangle -A SS-MASK -p tcp -j MARK --set-mark 0x2333
#ip6tables -t mangle -A SS-MASK -p udp -j MARK --set-mark 0x2333
#ip6tables -t mangle -A SS-MASK -p tcp -j MARK --set-mark 0x2333
iptables -t mangle -A SS-MARK -p udp -j MARK --set-mark 0x2333
iptables -t mangle -A SS-MARK -p tcp -j MARK --set-mark 0x2333
#ip6tables -t mangle -A SS-MARK -p udp -j MARK --set-mark 0x2333
#ip6tables -t mangle -A SS-MARK -p tcp -j MARK --set-mark 0x2333

# Apply
iptables -t mangle -A OUTPUT -j SS-MASK
#ip6tables -t mangle -A OUTPUT -j SS-MASK
iptables -t mangle -A OUTPUT -j SS-MARK
#ip6tables -t mangle -A OUTPUT -j SS-MARK
49 changes: 31 additions & 18 deletions crates/shadowsocks/src/relay/tcprelay/aead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ pub struct DecryptedReader {
cipher: Option<Cipher>,
buffer: BytesMut,
method: CipherKind,
salt: Option<Bytes>,
}

impl DecryptedReader {
Expand All @@ -79,13 +80,15 @@ impl DecryptedReader {
cipher: None,
buffer: BytesMut::with_capacity(method.salt_len()),
method,
salt: None,
}
} else {
DecryptedReader {
state: DecryptReadState::ReadLength,
cipher: Some(Cipher::new(method, key, &[])),
buffer: BytesMut::with_capacity(2 + method.tag_len()),
method,
salt: None,
}
}
}
Expand All @@ -105,7 +108,7 @@ impl DecryptedReader {
match self.state {
DecryptReadState::WaitSalt { ref key } => {
let key = unsafe { &*(key.as_ref() as *const _) };
ready!(self.poll_read_salt(cx, context, stream, key))?;
ready!(self.poll_read_salt(cx, stream, key))?;

self.buffer.clear();
self.state = DecryptReadState::ReadLength;
Expand All @@ -122,7 +125,7 @@ impl DecryptedReader {
}
},
DecryptReadState::ReadData { length } => {
ready!(self.poll_read_data(cx, stream, length))?;
ready!(self.poll_read_data(cx, context, stream, length))?;

self.state = DecryptReadState::BufferedData { pos: 0 };
}
Expand All @@ -146,13 +149,7 @@ impl DecryptedReader {
}
}

fn poll_read_salt<S>(
&mut self,
cx: &mut task::Context<'_>,
context: &Context,
stream: &mut S,
key: &[u8],
) -> Poll<io::Result<()>>
fn poll_read_salt<S>(&mut self, cx: &mut task::Context<'_>, stream: &mut S, key: &[u8]) -> Poll<io::Result<()>>
where
S: AsyncRead + Unpin + ?Sized,
{
Expand All @@ -164,14 +161,10 @@ impl DecryptedReader {
}

let salt = &self.buffer[..salt_len];
if context.check_nonce_and_set(&salt) {
use std::io::Error;

trace!("detected repeated AEAD salt {:?}", ByteStr::new(&salt));

let err = Error::new(ErrorKind::Other, "detected repeated salt");
return Err(err).into();
}
// #442 Remember salt in filter after first successful decryption.
//
// If we check salt right here will allow attacker to flood our filter and eventually block all of our legitimate clients' requests.
self.salt = Some(Bytes::copy_from_slice(salt));

trace!("got AEAD salt {:?}", ByteStr::new(salt));

Expand Down Expand Up @@ -201,7 +194,13 @@ impl DecryptedReader {
Ok(Some(length)).into()
}

fn poll_read_data<S>(&mut self, cx: &mut task::Context<'_>, stream: &mut S, size: usize) -> Poll<io::Result<()>>
fn poll_read_data<S>(
&mut self,
cx: &mut task::Context<'_>,
context: &Context,
stream: &mut S,
size: usize,
) -> Poll<io::Result<()>>
where
S: AsyncRead + Unpin + ?Sized,
{
Expand All @@ -219,6 +218,20 @@ impl DecryptedReader {
return Err(io::Error::new(ErrorKind::Other, "invalid tag-in")).into();
}

// Check repeated salt after first successful decryption #442
if self.salt.is_some() {
let salt = self.salt.take().unwrap();

if context.check_nonce_and_set(&salt) {
use std::io::Error;

trace!("detected repeated AEAD salt {:?}", ByteStr::new(&salt));

let err = Error::new(ErrorKind::Other, "detected repeated salt");
return Err(err).into();
}
}

// Remote TAG
self.buffer.truncate(size);

Expand Down

0 comments on commit a021cc4

Please sign in to comment.