diff --git a/sshuttle/cmdline.py b/sshuttle/cmdline.py index b40c832..ab45378 100644 --- a/sshuttle/cmdline.py +++ b/sshuttle/cmdline.py @@ -39,10 +39,11 @@ def main(): try: namespace = getattr(opt, 'namespace', None) - if namespace: + namespace_pid = getattr(opt, 'namespace_pid', None) + if namespace or namespace_pid: prefix = helpers.logprefix helpers.logprefix = 'ns: ' - enter_namespace(namespace) + enter_namespace(namespace, namespace_pid) helpers.logprefix = prefix if opt.firewall: diff --git a/sshuttle/namespace.py b/sshuttle/namespace.py index 9f00f30..43105c6 100644 --- a/sshuttle/namespace.py +++ b/sshuttle/namespace.py @@ -9,12 +9,15 @@ CLONE_NEWNET = 0x40000000 NETNS_RUN_DIR = "/var/run/netns" -def enter_namespace(namespace): - namespace_dir = f'{NETNS_RUN_DIR}/{namespace}' - +def enter_namespace(namespace, namespace_pid): + if namespace: + namespace_dir = f'{NETNS_RUN_DIR}/{namespace}' + else: + namespace_dir = f'/proc/{namespace_pid}/ns/net' + if not os.path.exists(namespace_dir): raise Fatal('The namespace %r does not exists.' % namespace_dir) - + debug2('loading libc') libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True) @@ -29,8 +32,9 @@ def enter_namespace(namespace): libc.setns.errcheck = errcheck # type: ignore - debug1('Entering namespace %r' % namespace) + debug1('Entering namespace %r' % namespace_dir) + with open(namespace_dir) as fd: libc.setns(fd.fileno(), CLONE_NEWNET) - debug1('Namespace %r successfully set' % namespace) + debug1('Namespace %r successfully set' % namespace_dir) diff --git a/sshuttle/options.py b/sshuttle/options.py index e19eef5..394cff6 100644 --- a/sshuttle/options.py +++ b/sshuttle/options.py @@ -474,5 +474,12 @@ if sys.platform == 'linux': parser.add_argument( '--namespace', type=parse_namespace, - help="Run it inside of a namespace." + help="Run inside of a net namespace with the given name." + ) + parser.add_argument( + '--namespace-pid', + type=int, + help=""" + Run inside the net namespace used by the process with + the given pid.""" )