mirror of
https://github.com/sshuttle/sshuttle.git
synced 2025-07-07 10:10:34 +02:00
iptables: more resilient startup/cleanup.
Now the sudo iptables subprocess persists for the entire life of sshuttle. The benefits of this are: - no need to authenticate again at shutdown (failure of which could cause us to not clean up iptables) - if the main process dies unexpectedly, iptables still gets cleaned up - the password prompt can happen *before* starting the ssh/server process, which means it'll stand out and the password prompt won't be overwritten.
This commit is contained in:
62
iptables.py
62
iptables.py
@ -22,24 +22,7 @@ def ipt(*args):
|
||||
raise Exception('%r returned %d' % (argv, rv))
|
||||
|
||||
|
||||
# This is some iptables voodoo for setting up the Linux kernel's transparent
|
||||
# proxying stuff. If subnets is empty, we just delete our sshuttle chain;
|
||||
# otherwise we delete it, then make it from scratch.
|
||||
#
|
||||
# We name the chain based on the transproxy port number so that it's possible
|
||||
# to run multiple copies of sshuttle at the same time. Of course, the
|
||||
# multiple copies shouldn't have overlapping subnets, or only the most-
|
||||
# recently-started one will win (because we use "-I OUTPUT 1" instead of
|
||||
# "-A OUTPUT").
|
||||
#
|
||||
# sshuttle is supposed to clean up after itself by deleting extra chains on
|
||||
# exit. In case that fails, it's not the end of the world; future runs will
|
||||
# supercede it in the transproxy list, at least, so the leftover iptables
|
||||
# chains are mostly harmless.
|
||||
def main(port, subnets):
|
||||
assert(port > 0)
|
||||
assert(port <= 65535)
|
||||
|
||||
def do_it(port, subnets):
|
||||
chain = 'sshuttle-%s' % port
|
||||
|
||||
# basic cleanup/setup of chains
|
||||
@ -63,4 +46,45 @@ def main(port, subnets):
|
||||
'--to-ports', str(port),
|
||||
'-m', 'ttl', '!', '--ttl', '42' # to prevent infinite loops
|
||||
)
|
||||
subnets_str = ['%s/%d' % (ip,width) for ip,width in subnets]
|
||||
|
||||
|
||||
# This is some iptables voodoo for setting up the Linux kernel's transparent
|
||||
# proxying stuff. If subnets is empty, we just delete our sshuttle chain;
|
||||
# otherwise we delete it, then make it from scratch.
|
||||
#
|
||||
# We name the chain based on the transproxy port number so that it's possible
|
||||
# to run multiple copies of sshuttle at the same time. Of course, the
|
||||
# multiple copies shouldn't have overlapping subnets, or only the most-
|
||||
# recently-started one will win (because we use "-I OUTPUT 1" instead of
|
||||
# "-A OUTPUT").
|
||||
#
|
||||
# This code is supposed to clean up after itself by deleting extra chains on
|
||||
# exit. In case that fails, it's not the end of the world; future runs will
|
||||
# supercede it in the transproxy list, at least, so the leftover iptables
|
||||
# chains are mostly harmless.
|
||||
def main(port, subnets):
|
||||
assert(port > 0)
|
||||
assert(port <= 65535)
|
||||
|
||||
debug1('iptables manager ready.\n')
|
||||
sys.stdout.write('READY\n')
|
||||
sys.stdout.flush()
|
||||
|
||||
# ctrl-c shouldn't be passed along to me. When the main sshuttle dies,
|
||||
# I'll die automatically.
|
||||
os.setsid()
|
||||
|
||||
# we wait until we get some input before creating the rules. That way,
|
||||
# sshuttle can launch us as early as possible (and get sudo password
|
||||
# authentication as early in the startup process as possible).
|
||||
sys.stdin.readline()
|
||||
try:
|
||||
do_it(port, subnets)
|
||||
|
||||
# Now we wait until EOF or any other kind of exception. We need
|
||||
# to stay running so that we don't need a *second* password
|
||||
# authentication at shutdown time - that cleanup is important!
|
||||
while sys.stdin.readline():
|
||||
pass
|
||||
finally:
|
||||
do_it(port, [])
|
||||
|
Reference in New Issue
Block a user