feat: switch to a network namespace on Linux

* Add support to run inside Linux namespace

**Motivation:**
In a specific use case, we use sshuttle to provide access to private
networks from multiple sites to a specific host. The sites may contain
networks that overlap each other, so each site is accessed inside a
different namespace that provides process-level network isolation and
prevents network overlap.

**Objective:**
This commit just adds a convenient way of spawning multiple sshuttle
instances inside different namespaces from a single process, by passing
the namespace's name though the variable --namespace. The result is the
same as calling `ip netns exec $NAMESPACE sshuttle ...`

* Add the argument --namespace-pid

The argument '--namespace-pid' allows sshuttle to attach to the same net
namespace used by a running process.

* PEP-8 compliance

* Add comment

* Make --namespace and --namespace-pid mutually exclusive.

* Prevent UnicodeDecodeError parsing iptables rule with comments

If one or more iptables rule contains a comment with a non-unicode character, an UnicodeDecodeError would be raised.
This commit is contained in:
jraylan
2025-02-08 18:48:55 -03:00
committed by GitHub
parent cbe3d1e402
commit 8a123d9762
4 changed files with 107 additions and 0 deletions

View File

@ -176,3 +176,33 @@ def test_parse_subnetport_host_with_port(mock_getaddrinfo):
(socket.AF_INET6, '2404:6800:4004:821::2001', 128, 80, 90),
(socket.AF_INET, '142.251.42.129', 32, 80, 90),
])
def test_parse_namespace():
valid_namespaces = [
'my_namespace',
'my.namespace',
'my_namespace_with_underscore',
'MyNamespace',
'@my_namespace',
'my.long_namespace.with.multiple.dots',
'@my.long_namespace.with.multiple.dots',
'my.Namespace.With.Mixed.Case',
]
for namespace in valid_namespaces:
assert sshuttle.options.parse_namespace(namespace) == namespace
invalid_namespaces = [
'',
'123namespace',
'my-namespace',
'my_namespace!',
'.my_namespace',
'my_namespace.',
'my..namespace',
]
for namespace in invalid_namespaces:
with pytest.raises(Fatal, match="'.*' is not a valid namespace name."):
sshuttle.options.parse_namespace(namespace)