Skip to content

Commit

Permalink
Merge branch 'pull/31'
Browse files Browse the repository at this point in the history
* Merging pull request apenwarr#31.
  • Loading branch information
Hasimir committed Jun 24, 2015
2 parents 284ebd2 + cdc63a6 commit bedf89e
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 24 deletions.
7 changes: 6 additions & 1 deletion Documentation/sshuttle.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ entire subnet to the VPN.
single IP address), 1.2.3.4/32 (equivalent to 1.2.3.4),
1.2.3.0/24 (a 24-bit subnet, ie. with a 255.255.255.0
netmask), and 0/0 ('just route everything through the
VPN').
VPN'). In addition, it is also possible to filter
additionally on the tcp port to include/exclude.
This is done by adding :port at the end of your netmask.
Note that `:port` is also valid. In this case, the netmask
will be defaulted to 0/0. Valid examples are `:80`,
`0:80`, `1.2.3.4:80` and `1.2.3.4/24:80`.

-l, --listen=*[ip:]port*
: use this ip address and port number as the transparent
Expand Down
8 changes: 4 additions & 4 deletions client.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,10 @@ def check(self):

def start(self):
self.pfile.write('ROUTES\n')
for (ip,width) in self.subnets_include+self.auto_nets:
self.pfile.write('%d,0,%s\n' % (width, ip))
for (ip,width) in self.subnets_exclude:
self.pfile.write('%d,1,%s\n' % (width, ip))
for (ip,width,port) in self.subnets_include+self.auto_nets:
self.pfile.write('%d,%d,0,%s\n' % (width, port, ip))
for (ip,width,port) in self.subnets_exclude:
self.pfile.write('%d,%d,1,%s\n' % (width, port, ip))
self.pfile.write('GO\n')
self.pfile.flush()
line = self.pfile.readline()
Expand Down
64 changes: 49 additions & 15 deletions firewall.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# vim: set tabstop=4 expandtab :

import re, errno, socket, select, signal, struct
import compat.ssubprocess as ssubprocess
import helpers, ssyslog
Expand Down Expand Up @@ -106,17 +108,36 @@ def do_iptables(port, dnsport, route_username, excludedports, subnets):
# to least-specific, and at any given level of specificity, we want
# excludes to come first. That's why the columns are in such a non-
# intuitive order.
for swidth,sexclude,snet in sorted(subnets, reverse=True):
for swidth,sport,sexclude,snet in sorted(subnets, reverse=True):
if sexclude:
ipt('-A', chain, '-j', 'RETURN',
'--dest', '%s/%s' % (snet,swidth),
'-p', 'tcp')
if sport > 0:
ipt('-A', chain, '-j', 'RETURN',
'--dest', '%s/%s' % (snet,swidth),
'-m', 'tcp',
'--dport', '%d' % sport,
'-p', 'tcp')
else:
ipt('-A', chain, '-j', 'RETURN',
'--dest', '%s/%s' % (snet,swidth),
'-p', 'tcp')
else:
ipt_ttl('-A', chain, '-j', 'REDIRECT',
if sport > 0:
ipt_ttl('-A', chain, '-j', 'REDIRECT',
'--dest', '%s/%s' % (snet,swidth),
'-m', 'tcp',
'--dport', '%d' % sport,
'-p', 'tcp',
<<<<<<< HEAD
'--to-ports', str(port),
*eportsargv)
=======
'--to-ports', str(port))
else:
ipt_ttl('-A', chain, '-j', 'REDIRECT',
'--dest', '%s/%s' % (snet,swidth),
'-p', 'tcp',
'--to-ports', str(port))
>>>>>>> pull/31

if dnsport:
for ip in nslist:
Expand Down Expand Up @@ -327,16 +348,29 @@ def do_ipfw(port, dnsport, route_username, excludedports, subnets):

if subnets:
# create new subnet entries
for swidth,sexclude,snet in sorted(subnets, reverse=True):
for swidth,dport,sexclude,snet in sorted(subnets, reverse=True):
if sexclude:
ipfw('add', sport, 'skipto', xsport,
'tcp',
'from', 'any', 'to', '%s/%s' % (snet,swidth))
if dport > 0:
ipfw('add', sport, 'skipto', xsport,
'tcp',
'from', 'any', 'to', '%s/%s' % (snet,swidth),
'%d' % dport)
else:
ipfw('add', sport, 'skipto', xsport,
'tcp',
'from', 'any', 'to', '%s/%s' % (snet,swidth))
else:
ipfw('add', sport, 'fwd', '127.0.0.1,%d' % port,
'tcp',
'from', 'any', 'to', '%s/%s' % (snet,swidth),
'not', 'ipttl', '42', 'keep-state', 'setup')
if dport > 0:
ipfw('add', sport, 'fwd', '127.0.0.1,%d' % port,
'tcp',
'from', 'any', 'to', '%s/%s' % (snet,swidth),
'%d' % dport,
'not', 'ipttl', '42', 'keep-state', 'setup')
else:
ipfw('add', sport, 'fwd', '127.0.0.1,%d' % port,
'tcp',
'from', 'any', 'to', '%s/%s' % (snet,swidth),
'not', 'ipttl', '42', 'keep-state', 'setup')

# This part is much crazier than it is on Linux, because MacOS (at least
# 10.6, and probably other versions, and maybe FreeBSD too) doesn't
Expand Down Expand Up @@ -529,10 +563,10 @@ def main(port, dnsport, syslog, route_username, excludedports):
elif line == 'GO\n':
break
try:
(width,exclude,ip) = line.strip().split(',', 2)
(width,dport,exclude,ip) = line.strip().split(',', 3)
except:
raise Fatal('firewall: expected route or GO but got %r' % line)
subnets.append((int(width), bool(int(exclude)), ip))
subnets.append((int(width), int(dport), bool(int(exclude)), ip))

try:
if line:
Expand Down
17 changes: 13 additions & 4 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# vim: set tabstop=4 expandtab :
import sys, os, re
import helpers, options, client, server, firewall, hostwatch
import compat.ssubprocess as ssubprocess
Expand All @@ -9,11 +10,16 @@
def parse_subnets(subnets_str):
subnets = []
for s in subnets_str:
m = re.match(r'(\d+)(?:\.(\d+)\.(\d+)\.(\d+))?(?:/(\d+))?$', s)
m = re.match(r'(\d+)?(?:\.(\d+)\.(\d+)\.(\d+))?(?:/(\d+))?(:\d+)?$', s)
if not m:
raise Fatal('%r is not a valid IP subnet format' % s)
(a,b,c,d,width) = m.groups()
(a,b,c,d,width,port) = m.groups()
(a,b,c,d) = (int(a or 0), int(b or 0), int(c or 0), int(d or 0))
if port == None:
port = 0
else:
port = int(re.sub('^:','',port))

if width == None:
width = 32
else:
Expand All @@ -22,7 +28,10 @@ def parse_subnets(subnets_str):
raise Fatal('%d.%d.%d.%d has numbers > 255' % (a,b,c,d))
if width > 32:
raise Fatal('*/%d is greater than the maximum of 32' % width)
subnets.append(('%d.%d.%d.%d' % (a,b,c,d), width))
if port > 65535:
raise Fatal('*:%d is greater than the maximum of 65535' % port)
subnets.append(('%d.%d.%d.%d' % (a,b,c,d), width, port))

return subnets


Expand Down Expand Up @@ -57,7 +66,7 @@ def parse_ipport(s):
dns-hosts= capture DNS requests to these servers and forward (comma-separated)
python= path to python interpreter on the remote server
r,remote= ssh hostname (and optional username) of remote sshuttle server
x,exclude= exclude this subnet (can be used more than once)
x,exclude= exclude this subnet and/or port (can be used more than once)
exclude-from= exclude the subnets in a file (whitespace separated)
v,verbose increase debug message verbosity
e,ssh-cmd= the command to use to connect to the remote [ssh]
Expand Down

0 comments on commit bedf89e

Please sign in to comment.