summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvery Pennarun <apenwarr@gmail.com>2011-01-26 03:46:59 -0800
committerAvery Pennarun <apenwarr@gmail.com>2011-01-26 05:25:26 -0800
commitebfc3703ec209af8ec818394d5d623ead1a18d1d (patch)
tree47a4b0d76e0394281d4e9746f6222d4a784d7a9e
parent760740e9aa7861a6eba566b96f4b4a6371c1f29a (diff)
dns: add support for MacOS (but it doesn't work...)
...because stupid MacOS ipfw 'fwd' rules don't work quite right with udp. It can intercept packets bound for remote hosts, but it doesn't correctly rewrite the port number from its original to the new socket, so it gets dropped by the local kernel anyway. That is, a packet to 1.2.3.4:53 should be redirected to, say, 127.0.0.1:9999, the local DNS listener socket. But instead, it gets sent to 127.0.0.1:53, which nobody is listening on, so it gets eaten. Sigh.
-rw-r--r--firewall.py18
1 files changed, 15 insertions, 3 deletions
diff --git a/firewall.py b/firewall.py
index ed576a2..ccf576f 100644
--- a/firewall.py
+++ b/firewall.py
@@ -59,12 +59,13 @@ def do_iptables(port, dnsport, subnets):
ipt('-F', chain)
ipt('-X', chain)
- if subnets:
+ if subnets or dnsport:
ipt('-N', chain)
ipt('-F', chain)
ipt('-I', 'OUTPUT', '1', '-j', chain)
ipt('-I', 'PREROUTING', '1', '-j', chain)
+ if subnets:
# create new subnet entries. Note that we're sorting in a very
# particular order: we need to go from most-specific (largest swidth)
# to least-specific, and at any given level of specificity, we want
@@ -98,6 +99,7 @@ def ipfw_rule_exists(n):
for line in p.stdout:
if line.startswith('%05d ' % n):
if not ('ipttl 42 setup keep-state' in line
+ or 'ipttl 42 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())
@@ -167,13 +169,14 @@ def do_ipfw(port, dnsport, subnets):
oldval = _oldctls[name]
_sysctl_set(name, oldval)
- if subnets:
+ if subnets or dnsport:
sysctl_set('net.inet.ip.fw.enable', 1)
sysctl_set('net.inet.ip.scopedroute', 0)
ipfw('add', sport, 'check-state', 'ip',
'from', 'any', 'to', 'any')
-
+
+ if subnets:
# create new subnet entries
for swidth,sexclude,snet in sorted(subnets, reverse=True):
if sexclude:
@@ -186,6 +189,14 @@ def do_ipfw(port, dnsport, subnets):
'from', 'any', 'to', '%s/%s' % (snet,swidth),
'not', 'ipttl', '42', 'keep-state', 'setup')
+ if dnsport:
+ nslist = resolvconf_nameservers()
+ for ip in nslist:
+ ipfw('add', sport, 'fwd', '127.0.0.1,%d' % dnsport,
+ 'log', 'udp',
+ 'from', 'any', 'to', '%s/32' % ip, '53',
+ 'not', 'ipttl', '42', 'keep-state')
+
def program_exists(name):
paths = (os.getenv('PATH') or os.defpath).split(os.pathsep)
@@ -194,6 +205,7 @@ def program_exists(name):
if os.path.exists(fn):
return not os.path.isdir(fn) and os.access(fn, os.X_OK)
+
hostmap = {}
def rewrite_etc_hosts(port):
HOSTSFILE='/etc/hosts'