Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def nft_get_handle(expression, chain):
cmd = 'nft'
argv = [cmd, 'list', expression, '-a']
env = {
'PATH': os.environ['PATH'],
'LC_ALL': "C",
}
try:
output = ssubprocess.check_output(argv, env=env)
for line in output.decode('utf-8').split('\n'):
if ('jump %s' % chain) in line:
return re.sub('.*# ', '', line)
except ssubprocess.CalledProcessError as e:
raise Fatal('%r returned %d' % (argv, e.returncode))
def pfctl(args, stdin=None):
argv = ['pfctl'] + shlex.split(args)
debug1('>> %s\n' % ' '.join(argv))
env = {
'PATH': os.environ['PATH'],
'LC_ALL': "C",
}
p = ssubprocess.Popen(argv, stdin=ssubprocess.PIPE,
stdout=ssubprocess.PIPE,
stderr=ssubprocess.PIPE,
env=env)
o = p.communicate(stdin)
if p.returncode:
raise Fatal('%r returned %d' % (argv, p.returncode))
return o
mux = Mux(serversock, serversock)
handlers.append(mux)
expected = b'SSHUTTLE0001'
try:
v = 'x'
while v and v != b'\0':
v = serversock.recv(1)
v = 'x'
while v and v != b'\0':
v = serversock.recv(1)
initstring = serversock.recv(len(expected))
except socket.error as e:
if e.args[0] == errno.ECONNRESET:
raise Fatal("failed to establish ssh session (2)")
else:
raise
rv = serverproc.poll()
if rv:
raise Fatal('server died with error code %d' % rv)
if initstring != expected:
raise Fatal('expected server init string %r; got %r'
% (expected, initstring))
log('Connected.\n')
sys.stdout.flush()
if daemon:
daemonize()
log('daemonizing (%s).\n' % _pidname)
# These should never fail.
# If these do fail, something is broken above.
if subnets_v6:
assert required.ipv6
if redirectport_v6 == 0:
raise Fatal("IPv6 subnets defined but not listening")
if nslist_v6:
assert required.dns
assert required.ipv6
if dnsport_v6 == 0:
raise Fatal("IPv6 ns servers defined but not listening")
if subnets_v4:
if redirectport_v4 == 0:
raise Fatal("IPv4 subnets defined but not listening")
if nslist_v4:
if dnsport_v4 == 0:
raise Fatal("IPv4 ns servers defined but not listening")
# setup method specific stuff on listeners
fw.method.setup_tcp_listener(tcp_listener)
if udp_listener:
fw.method.setup_udp_listener(udp_listener)
if dns_listener:
fw.method.setup_udp_listener(dns_listener)
# start the firewall
fw.setup(subnets_include, subnets_exclude, nslist,
redirectport_v6, redirectport_v4, dnsport_v6, dnsport_v4,
required.udp, user)
avail = fw.method.get_supported_features()
required = Features()
if listenip_v6 == "auto":
if avail.ipv6:
listenip_v6 = ('::1', 0)
else:
listenip_v6 = None
if user is not None:
if getpwnam is None:
raise Fatal("Routing by user not available on this system.")
try:
user = getpwnam(user).pw_uid
except KeyError:
raise Fatal("User %s does not exist." % user)
if fw.method.name != 'nat':
required.ipv6 = len(subnets_v6) > 0 or listenip_v6 is not None
required.ipv4 = len(subnets_v4) > 0 or listenip_v4 is not None
else:
required.ipv6 = None
required.ipv4 = None
required.udp = avail.udp
required.dns = len(nslist) > 0
required.user = False if user is None else True
# if IPv6 not supported, ignore IPv6 DNS servers
if not required.ipv6:
nslist_v6 = []
nslist = nslist_v4
family = int(data)
mux.channels[channel] = lambda cmd, data: udp_req(channel, cmd, data)
if channel in udphandlers:
raise Fatal('UDP connection channel %d already open' % channel)
else:
h = UdpProxy(mux, channel, family)
handlers.append(h)
udphandlers[channel] = h
mux.got_udp_open = udp_open
while mux.ok:
if hw.pid:
assert(hw.pid > 0)
(rpid, rv) = os.waitpid(hw.pid, os.WNOHANG)
if rpid:
raise Fatal(
'hostwatch exited unexpectedly: code 0x%04x\n' % rv)
ssnet.runonce(handlers, mux)
if latency_control:
mux.check_fullness()
if dnshandlers:
now = time.time()
remove = []
for channel, h in dnshandlers.items():
if h.timeout < now or not h.ok:
debug3('expiring dnsreqs channel=%d\n' % channel)
remove.append(channel)
h.ok = False
for channel in remove:
del dnshandlers[channel]
def ipt(family, table, *args):
if family == socket.AF_INET6:
argv = ['ip6tables', '-t', table] + list(args)
elif family == socket.AF_INET:
argv = ['iptables', '-t', table] + list(args)
else:
raise Exception('Unsupported family "%s"' % family_to_string(family))
debug1('>> %s\n' % ' '.join(argv))
env = {
'PATH': os.environ['PATH'],
'LC_ALL': "C",
}
rv = ssubprocess.call(argv, env=env)
if rv:
raise Fatal('%r returned %d' % (argv, rv))
def setup_daemon():
if os.getuid() != 0:
raise Fatal('you must be root (or enable su/sudo) to set the firewall')
# don't disappear if our controlling terminal or stdout/stderr
# disappears; we still have to clean up.
signal.signal(signal.SIGHUP, signal.SIG_IGN)
signal.signal(signal.SIGPIPE, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)
signal.signal(signal.SIGINT, signal.SIG_IGN)
# ctrl-c shouldn't be passed along to me. When the main sshuttle dies,
# I'll die automatically.
os.setsid()
# because of limitations of the 'su' command, the *real* stdin/stdout
# are both attached to stdout initially. Clone stdout into stdin so we
# can read from it.
os.dup2(1, 0)
def nft(family, table, action, *args):
if family == socket.AF_INET:
argv = ['nft', action, 'ip', table] + list(args)
elif family == socket.AF_INET6:
argv = ['nft', action, 'ip6', table] + list(args)
else:
raise Exception('Unsupported family "%s"' % family_to_string(family))
debug1('>> %s\n' % ' '.join(argv))
env = {
'PATH': os.environ['PATH'],
'LC_ALL': "C",
}
rv = ssubprocess.call(argv, env=env)
if rv:
raise Fatal('%r returned %d' % (argv, rv))
opt.auto_nets,
includes,
excludes,
opt.daemon,
opt.to_ns,
opt.pidfile,
opt.user,
opt.sudo_pythonpath)
if return_code == 0:
log('Normal exit code, exiting...')
else:
log('Abnormal exit code %d detected, failing...' % return_code)
return return_code
except Fatal as e:
log('fatal: %s\n' % e)
return 99
except KeyboardInterrupt:
log('\n')
log('Keyboard interrupt: exiting.\n')
return 1