Skip to content

Commit 432e98c

Browse files
committed
auto-hosts: don't add hosts that aren't being routed by sshuttle.
I've been meaning to add this patch for a long time, but it's especially important once we add FQDN support to --auto-hosts. Basically, auto-hosts will still discover all the hostnames it can, but we'll only add them to /etc/hosts if their IP address is in one of the routed subnet ranges. That prevents polluting the /etc/hosts file with cruft.
1 parent 29d2e06 commit 432e98c

File tree

3 files changed

+25
-13
lines changed

3 files changed

+25
-13
lines changed

firewall.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,19 @@ def restore_etc_hosts(port):
430430
rewrite_etc_hosts(port)
431431

432432

433+
def _mask(ip, width):
434+
nip = struct.unpack('!I', socket.inet_aton(ip))[0]
435+
masked = nip & shl(shl(1, width) - 1, 32-width)
436+
return socket.inet_ntoa(struct.pack('!I', masked))
437+
438+
439+
def ip_in_subnets(ip, subnets):
440+
for swidth,sexclude,snet in sorted(subnets, reverse=True):
441+
if _mask(snet, swidth) == _mask(ip, swidth):
442+
return not sexclude
443+
return False
444+
445+
433446
# This is some voodoo for setting up the kernel's transparent
434447
# proxying stuff. If subnets is empty, we just delete our sshuttle rules;
435448
# otherwise we delete it, then make them from scratch.
@@ -521,8 +534,9 @@ def main(port, dnsport, syslog):
521534
line = sys.stdin.readline(128)
522535
if line.startswith('HOST '):
523536
(name,ip) = line[5:].strip().split(',', 1)
524-
hostmap[name] = ip
525-
rewrite_etc_hosts(port)
537+
if ip_in_subnets(ip, subnets):
538+
hostmap[name] = ip
539+
rewrite_etc_hosts(port)
526540
elif line:
527541
raise Fatal('expected EOF, got %r' % line)
528542
else:

helpers.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,10 @@ def islocal(ip):
7878
return True # it's a local IP, or there would have been an error
7979

8080

81+
def shl(n, bits):
82+
# we use our own implementation of left-shift because
83+
# results may be different between older and newer versions
84+
# of python for numbers like 1<<32. We use long() because
85+
# int(2**32) doesn't work in older python, which has limited
86+
# int sizes.
87+
return n * long(2**bits)

server.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,11 @@ def _maskbits(netmask):
3737
if not netmask:
3838
return 32
3939
for i in range(32):
40-
if netmask[0] & _shl(1, i):
40+
if netmask[0] & shl(1, i):
4141
return 32-i
4242
return 0
4343

4444

45-
def _shl(n, bits):
46-
# we use our own implementation of left-shift because
47-
# results may be different between older and newer versions
48-
# of python for numbers like 1<<32. We use long() because
49-
# int(2**32) doesn't work in older python, which has limited
50-
# int sizes.
51-
return n * long(2**bits)
52-
53-
5445
def _list_routes():
5546
argv = ['netstat', '-rn']
5647
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE)
@@ -63,7 +54,7 @@ def _list_routes():
6354
maskw = _ipmatch(cols[2]) # linux only
6455
mask = _maskbits(maskw) # returns 32 if maskw is null
6556
width = min(ipw[1], mask)
66-
ip = ipw[0] & _shl(_shl(1, width) - 1, 32-width)
57+
ip = ipw[0] & shl(shl(1, width) - 1, 32-width)
6758
routes.append((socket.inet_ntoa(struct.pack('!I', ip)), width))
6859
rv = p.wait()
6960
if rv != 0:

0 commit comments

Comments
 (0)