Skip to content

Commit 5a1ed2e

Browse files
committed
Added support to exclude ports from forwarding
1 parent 14f3d00 commit 5a1ed2e

File tree

3 files changed

+21
-13
lines changed

3 files changed

+21
-13
lines changed

client.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,17 @@ def original_dst(sock):
9696

9797

9898
class FirewallClient:
99-
def __init__(self, port, subnets_include, subnets_exclude, dnsport, route_username):
99+
def __init__(self, port, subnets_include, subnets_exclude, dnsport, route_username, excludedports):
100100
self.port = port
101101
self.auto_nets = []
102102
self.subnets_include = subnets_include
103103
self.subnets_exclude = subnets_exclude
104104
self.dnsport = dnsport
105105
argvbase = ([sys.argv[1], sys.argv[0], sys.argv[1]] +
106106
['-v'] * (helpers.verbose or 0) +
107-
['--firewall', str(port), str(dnsport), '--username', route_username])
107+
['--firewall', str(port), str(dnsport),
108+
'--username', route_username or '',
109+
'--eports', excludedports or ''])
108110
if ssyslog._p:
109111
argvbase += ['--syslog']
110112
argv_tries = [
@@ -338,7 +340,7 @@ def onhostlist(hostlist):
338340

339341
def main(listenip, ssh_cmd, remotename, python, latency_control, dns,
340342
seed_hosts, auto_nets,
341-
subnets_include, subnets_exclude, syslog, daemon, pidfile, route_username):
343+
subnets_include, subnets_exclude, syslog, daemon, pidfile, route_username, excludedports):
342344
if syslog:
343345
ssyslog.start_syslog()
344346
if daemon:
@@ -385,7 +387,7 @@ def main(listenip, ssh_cmd, remotename, python, latency_control, dns,
385387
dnsport = 0
386388
dnslistener = None
387389

388-
fw = FirewallClient(listenip[1], subnets_include, subnets_exclude, dnsport, route_username)
390+
fw = FirewallClient(listenip[1], subnets_include, subnets_exclude, dnsport, route_username, excludedports)
389391

390392
try:
391393
return _main(listener, fw, ssh_cmd, remotename,

firewall.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,13 @@ def ipt_ttl(*args):
7070
# multiple copies shouldn't have overlapping subnets, or only the most-
7171
# recently-started one will win (because we use "-I OUTPUT 1" instead of
7272
# "-A OUTPUT").
73-
def do_iptables(port, dnsport, route_username, subnets):
73+
def do_iptables(port, dnsport, route_username, excludedports, subnets):
7474
chain = 'sshuttle-%s' % port
7575

76+
eportsargv = []
77+
if excludedports:
78+
eportsargv += ['--match', 'multiport', '!', '--dport', excludedports]
79+
7680
# basic cleanup/setup of chains
7781
if ipt_chain_exists(chain):
7882
if not route_username:
@@ -107,8 +111,9 @@ def do_iptables(port, dnsport, route_username, subnets):
107111
ipt_ttl('-A', chain, '-j', 'REDIRECT',
108112
'--dest', '%s/%s' % (snet,swidth),
109113
'-p', 'tcp',
110-
'--to-ports', str(port))
111-
114+
'--to-ports', str(port),
115+
*eportsargv)
116+
112117
if dnsport:
113118
nslist = resolvconf_nameservers()
114119
for ip in nslist:
@@ -261,7 +266,7 @@ def ipfw(*args):
261266
_call(argv)
262267

263268

264-
def do_ipfw(port, dnsport, route_username, subnets):
269+
def do_ipfw(port, dnsport, route_username, excludedports, subnets):
265270
sport = str(port)
266271
xsport = str(port+1)
267272

@@ -457,7 +462,7 @@ def ip_in_subnets(ip, subnets):
457462
# exit. In case that fails, it's not the end of the world; future runs will
458463
# supercede it in the transproxy list, at least, so the leftover rules
459464
# are hopefully harmless.
460-
def main(port, dnsport, syslog, route_username):
465+
def main(port, dnsport, syslog, route_username, excludedports):
461466
assert(port > 0)
462467
assert(port <= 65535)
463468
assert(dnsport >= 0)
@@ -522,7 +527,7 @@ def main(port, dnsport, syslog, route_username):
522527
try:
523528
if line:
524529
debug1('firewall manager: starting transproxy.\n')
525-
do_wait = do_it(port, dnsport, route_username, subnets)
530+
do_wait = do_it(port, dnsport, route_username, excludedports, subnets)
526531
sys.stdout.write('STARTED\n')
527532

528533
try:
@@ -552,5 +557,5 @@ def main(port, dnsport, syslog, route_username):
552557
debug1('firewall manager: undoing changes.\n')
553558
except:
554559
pass
555-
do_it(port, 0, route_username, [])
560+
do_it(port, 0, route_username, excludedports, [])
556561
restore_etc_hosts(port)

main.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ def parse_ipport(s):
6868
syslog send log messages to syslog (default if you use --daemon)
6969
pidfile= pidfile name (only if using --daemon) [./sshuttle.pid]
7070
u,username= route packets only from the specified username (required iptables with -m owner support)
71+
eports= Exclude this list of ports (separated by comma with no spaces)
7172
server (internal use only)
7273
firewall (internal use only)
7374
hostwatch (internal use only)
@@ -95,7 +96,7 @@ def parse_ipport(s):
9596
elif opt.firewall:
9697
if len(extra) != 2:
9798
o.fatal('exactly two arguments expected')
98-
sys.exit(firewall.main(int(extra[0]), int(extra[1]), opt.syslog, opt.username))
99+
sys.exit(firewall.main(int(extra[0]), int(extra[1]), opt.syslog, opt.username, opt.eports))
99100
elif opt.hostwatch:
100101
sys.exit(hostwatch.hw_main(extra))
101102
else:
@@ -129,7 +130,7 @@ def parse_ipport(s):
129130
opt.auto_nets,
130131
parse_subnets(includes),
131132
parse_subnets(excludes),
132-
opt.syslog, opt.daemon, opt.pidfile, opt.username))
133+
opt.syslog, opt.daemon, opt.pidfile, opt.username, opt.eports))
133134
except FatalNeedsReboot, e:
134135
log('You must reboot before using sshuttle.\n')
135136
sys.exit(EXITCODE_NEEDS_REBOOT)

0 commit comments

Comments
 (0)