Commit 8b4466b8 authored by Avery Pennarun's avatar Avery Pennarun

BSD ipfw: switch from 'established' to 'keep-state/check-state'.

It turns out 'established' doesn't work the way I expected it to from
iptables; it's not stateful.  It just checks the TCP flags to see if the
connection *thinks* it's already established, and follows the rule if so.
That caused the first packet of each new connection to set sent to our
transproxy, but not the subsequent ones, so weird stuff happened.

With this change, any (matching) connection created *after* starting sshuttle
will get forwarded, but pre-existing ones - most importantly, sshuttle's own
ssh connection - will not.

And with this (plus the previous commit), sshuttle works on MacOS, including
10.6!
parent 4bf4f70c
...@@ -65,14 +65,19 @@ def do_iptables(port, subnets): ...@@ -65,14 +65,19 @@ def do_iptables(port, subnets):
def ipfw_rule_exists(n): def ipfw_rule_exists(n):
argv = ['ipfw', 'list'] argv = ['ipfw', 'list']
p = subprocess.Popen(argv, stdout = subprocess.PIPE) p = subprocess.Popen(argv, stdout = subprocess.PIPE)
found = False
for line in p.stdout: for line in p.stdout:
if line.startswith('%05d ' % n): if line.startswith('%05d ' % n):
if line.find('ipttl 42') < 0 and line.find('established') < 0: if not ('ipttl 42 setup keep-state' in line
or ('skipto %d' % (n+1)) in line
or 'check-state' in line):
log('non-sshuttle ipfw rule: %r\n' % line.strip())
raise Fatal('non-sshuttle ipfw rule #%d already exists!' % n) raise Fatal('non-sshuttle ipfw rule #%d already exists!' % n)
return True found = True
rv = p.wait() rv = p.wait()
if rv: if rv:
raise Fatal('%r returned %d' % (argv, rv)) raise Fatal('%r returned %d' % (argv, rv))
return found
def sysctl_get(name): def sysctl_get(name):
...@@ -127,8 +132,8 @@ def do_ipfw(port, subnets): ...@@ -127,8 +132,8 @@ def do_ipfw(port, subnets):
sysctl_set('net.inet.ip.forwarding', 1) sysctl_set('net.inet.ip.forwarding', 1)
sysctl_set('net.inet.ip.scopedroute', 0) sysctl_set('net.inet.ip.scopedroute', 0)
ipfw('add', sport, 'accept', 'ip', ipfw('add', sport, 'check-state', 'ip',
'from', 'any', 'to', 'any', 'established') 'from', 'any', 'to', 'any')
# create new subnet entries # create new subnet entries
for swidth,sexclude,snet in sorted(subnets, reverse=True): for swidth,sexclude,snet in sorted(subnets, reverse=True):
...@@ -140,7 +145,7 @@ def do_ipfw(port, subnets): ...@@ -140,7 +145,7 @@ def do_ipfw(port, subnets):
ipfw('add', sport, 'fwd', '127.0.0.1,%d' % port, ipfw('add', sport, 'fwd', '127.0.0.1,%d' % port,
'log', 'tcp', 'log', 'tcp',
'from', 'any', 'to', '%s/%s' % (snet,swidth), 'from', 'any', 'to', '%s/%s' % (snet,swidth),
'not', 'ipttl', '42') 'not', 'ipttl', '42', 'keep-state', 'setup')
def program_exists(name): def program_exists(name):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment