summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvery Pennarun <apenwarr@gmail.com>2011-02-04 21:55:40 -0800
committerAvery Pennarun <apenwarr@gmail.com>2011-02-04 21:55:40 -0800
commit4fde980f46daf9952f95f3c04cf2f12d57eba274 (patch)
treed9f087dd9eacfc8dbf9fc7434a05e5e16fc2035b
parent621997b279bd6b22e93f5df0b97c6f9044578b98 (diff)
firewall.py: MacOS: permanently set the net.inet.ip.scopedroute sysctl.sshuttle-0.51
If this sysctl isn't set to 0 at the time your network interface is brought up, and we later change it, then the MacOS (10.6.6 at least) ARP table gets totally confused and networking stops working about 15 minutes later, until you down and re-up the interface. The symptom is that pings outside your LAN would give results like this: ping: sendto: no route to host and "arp -a -n" would show *two* entries for your default gateway instead of just one. sshuttle was helpfully putting the sysctl back the way it was when it shuts down, so you would fix your network by downing the interface, so sshuttle would abort and change the sysctl back, then you would re-up the interface, then restart sshuttle, and sshuttle would change the sysctl back and restart the cycle: it would break again a few minutes later. That's annoying, and it gives sshuttle a bad reputation for being the thing that breaks your network. I can't find a *really* good workaround for the bug, so barring that, let's just permanently set the sysctl to 0 and not change it back on exit. That should just leave your computer back how it worked in MacOS 10.5, as far as I know, which seems harmless. At least I've been running my Mac that way for a few days and I haven't seen any weirdness. Now, doing *that* would still mean that the first sshuttle session after a reboot would still break the network, since sysctl changes are lost on reboot. Thus, let's be extra hardcore and write it to /etc/sysctl.conf so that it goes the way we want it after a reboot. Thus, sshuttle should break your network at most once. Which still sucks, but hopefully nobody will notice.
-rw-r--r--firewall.py18
1 files changed, 13 insertions, 5 deletions
diff --git a/firewall.py b/firewall.py
index c7557ed..7767d43 100644
--- a/firewall.py
+++ b/firewall.py
@@ -131,11 +131,11 @@ def _fill_oldctls(prefix):
def _sysctl_set(name, val):
argv = ['sysctl', '-w', '%s=%s' % (name, val)]
debug1('>> %s\n' % ' '.join(argv))
- rv = ssubprocess.call(argv, stdout = open('/dev/null', 'w'))
+ return ssubprocess.call(argv, stdout = open('/dev/null', 'w'))
_changedctls = []
-def sysctl_set(name, val):
+def sysctl_set(name, val, permanent=False):
PREFIX = 'net.inet.ip'
assert(name.startswith(PREFIX + '.'))
val = str(val)
@@ -146,8 +146,16 @@ def sysctl_set(name, val):
return
oldval = _oldctls[name]
if val != oldval:
- _changedctls.append(name)
- return _sysctl_set(name, val)
+ rv = _sysctl_set(name, val)
+ if rv==0 and permanent:
+ debug1('>> ...saving permanently in /etc/sysctl.conf\n')
+ f = open('/etc/sysctl.conf', 'a')
+ f.write('\n'
+ '# Added by sshuttle\n'
+ '%s=%s\n' % (name, val))
+ f.close()
+ else:
+ _changedctls.append(name)
def _udp_unpack(p):
@@ -206,7 +214,7 @@ def do_ipfw(port, dnsport, subnets):
if subnets or dnsport:
sysctl_set('net.inet.ip.fw.enable', 1)
- sysctl_set('net.inet.ip.scopedroute', 0)
+ sysctl_set('net.inet.ip.scopedroute', 0, permanent=True)
ipfw('add', sport, 'check-state', 'ip',
'from', 'any', 'to', 'any')