mirror of
https://github.com/sshuttle/sshuttle.git
synced 2025-08-10 08:07:40 +02:00
iptables.py: completely replace ipt script.
Doing it in python instead of shell makes the code a bit less error prone. Plus we can parse the iptables output and avoid triggering iptables errors.
This commit is contained in:
27
client.py
27
client.py
@ -21,16 +21,7 @@ def iptables_setup(port, subnets):
|
|||||||
raise Exception('%r returned %d' % (argv, rv))
|
raise Exception('%r returned %d' % (argv, rv))
|
||||||
|
|
||||||
|
|
||||||
def main(listenip, remotename, subnets):
|
def _main(listener, remotename, subnets):
|
||||||
log('Starting sshuttle proxy.\n')
|
|
||||||
listener = socket.socket()
|
|
||||||
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
||||||
listener.bind(listenip)
|
|
||||||
listener.listen(10)
|
|
||||||
log('Listening on %r.\n' % (listener.getsockname(),))
|
|
||||||
|
|
||||||
iptables_setup(listenip[1], subnets)
|
|
||||||
|
|
||||||
handlers = []
|
handlers = []
|
||||||
def onaccept():
|
def onaccept():
|
||||||
sock,srcip = listener.accept()
|
sock,srcip = listener.accept()
|
||||||
@ -61,3 +52,19 @@ def main(listenip, remotename, subnets):
|
|||||||
for s in handlers:
|
for s in handlers:
|
||||||
if s.socks & ready:
|
if s.socks & ready:
|
||||||
s.callback()
|
s.callback()
|
||||||
|
|
||||||
|
|
||||||
|
def main(listenip, remotename, subnets):
|
||||||
|
log('Starting sshuttle proxy.\n')
|
||||||
|
listener = socket.socket()
|
||||||
|
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
listener.bind(listenip)
|
||||||
|
listener.listen(10)
|
||||||
|
log('Listening on %r.\n' % (listener.getsockname(),))
|
||||||
|
|
||||||
|
iptables_setup(listenip[1], subnets)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return _main(listener, remotename, subnets)
|
||||||
|
finally:
|
||||||
|
iptables_setup(listenip[1], [])
|
||||||
|
28
ipt
28
ipt
@ -1,28 +0,0 @@
|
|||||||
#!/bin/bash -x
|
|
||||||
PORT="$1"
|
|
||||||
shift
|
|
||||||
|
|
||||||
if [ -z "$PORT" ] || ! [ "$PORT" -gt 0 ]; then
|
|
||||||
echo "'$PORT' is not a valid port number"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# basic cleanup/setup
|
|
||||||
C=sshuttle-$PORT
|
|
||||||
iptables -t nat -D OUTPUT -j $C
|
|
||||||
iptables -t nat -F $C
|
|
||||||
iptables -t nat -X $C
|
|
||||||
|
|
||||||
if [ -z "$*" ]; then
|
|
||||||
# just delete existing rules
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
iptables -t nat -N $C
|
|
||||||
iptables -t nat -I OUTPUT 1 -j $C
|
|
||||||
iptables -t nat -D $C -j REDIRECT -p tcp --to-ports $PORT
|
|
||||||
|
|
||||||
# create new subnet entries
|
|
||||||
for subnet in "$@"; do
|
|
||||||
iptables -t nat -A $C -j REDIRECT --dest "$subnet" -p tcp \
|
|
||||||
--to-ports "$PORT" -m ttl \! --ttl 42
|
|
||||||
done
|
|
49
iptables.py
49
iptables.py
@ -1,5 +1,50 @@
|
|||||||
import subprocess
|
import subprocess, re
|
||||||
|
from helpers import *
|
||||||
|
|
||||||
|
|
||||||
|
def chain_exists(name):
|
||||||
|
argv = ['iptables', '-t', 'nat', '-nL']
|
||||||
|
p = subprocess.Popen(argv, stdout = subprocess.PIPE)
|
||||||
|
for line in p.stdout:
|
||||||
|
if line.startswith('Chain %s ' % name):
|
||||||
|
return True
|
||||||
|
rv = p.wait()
|
||||||
|
if rv:
|
||||||
|
raise Exception('%r returned %d' % (argv, rv))
|
||||||
|
|
||||||
|
|
||||||
|
def ipt(*args):
|
||||||
|
argv = ['iptables', '-t', 'nat'] + list(args)
|
||||||
|
log('>> %s\n' % ' '.join(argv))
|
||||||
|
rv = subprocess.call(argv)
|
||||||
|
if rv:
|
||||||
|
raise Exception('%r returned %d' % (argv, rv))
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME: this prints scary-looking errors
|
||||||
def main(port, subnets):
|
def main(port, subnets):
|
||||||
|
assert(port > 0)
|
||||||
|
assert(port <= 65535)
|
||||||
|
|
||||||
|
chain = 'sshuttle-%s' % port
|
||||||
|
|
||||||
|
# basic cleanup/setup of chains
|
||||||
|
if chain_exists(chain):
|
||||||
|
ipt('-D', 'OUTPUT', '-j', chain)
|
||||||
|
ipt('-F', chain)
|
||||||
|
ipt('-X', chain)
|
||||||
|
|
||||||
|
if subnets:
|
||||||
|
ipt('-N', chain)
|
||||||
|
ipt('-F', chain)
|
||||||
|
ipt('-I', 'OUTPUT', '1', '-j', chain)
|
||||||
|
|
||||||
|
# create new subnet entries
|
||||||
|
for snet,swidth in subnets:
|
||||||
|
ipt('-A', chain, '-j', 'REDIRECT',
|
||||||
|
'--dest', '%s/%s' % (snet,swidth),
|
||||||
|
'-p', 'tcp',
|
||||||
|
'--to-ports', str(port),
|
||||||
|
'-m', 'ttl', '!', '--ttl', '42' # to prevent infinite loops
|
||||||
|
)
|
||||||
subnets_str = ['%s/%d' % (ip,width) for ip,width in subnets]
|
subnets_str = ['%s/%d' % (ip,width) for ip,width in subnets]
|
||||||
subprocess.call(['./ipt', str(port)] + subnets_str)
|
|
||||||
|
2
main.py
2
main.py
@ -8,7 +8,7 @@ import options, client, iptables
|
|||||||
def parse_subnets(subnets_str):
|
def parse_subnets(subnets_str):
|
||||||
subnets = []
|
subnets = []
|
||||||
for s in subnets_str:
|
for s in subnets_str:
|
||||||
m = re.match(r'(\d+)\.(\d+)\.(\d+)\.(\d+)(?:/(\d+))?$', s)
|
m = re.match(r'(\d+)(?:\.(\d+)\.(\d+)\.(\d+))?(?:/(\d+))?$', s)
|
||||||
if not m:
|
if not m:
|
||||||
raise Exception('%r is not a valid IP subnet format' % s)
|
raise Exception('%r is not a valid IP subnet format' % s)
|
||||||
(a,b,c,d,width) = m.groups()
|
(a,b,c,d,width) = m.groups()
|
||||||
|
Reference in New Issue
Block a user