diff options
author | Scott Kuhl <kuhl@mtu.edu> | 2020-10-26 17:24:32 -0400 |
---|---|---|
committer | Scott Kuhl <kuhl@mtu.edu> | 2020-10-26 17:24:32 -0400 |
commit | 34f538ff9899c4267e735d4ecd528610d76c1631 (patch) | |
tree | 97525350ba24cf6e1f9628ede100172057f1665a /sshuttle/methods | |
parent | 68c9c9bbcd75e43c7e0326f8da796df9876b0334 (diff) | |
parent | 5c8c7072080d1f29323767caf2495ecebf1ea8e4 (diff) |
Merge branch 'master' into which-fix to resolve merge conflict.
Diffstat (limited to 'sshuttle/methods')
-rw-r--r-- | sshuttle/methods/__init__.py | 26 | ||||
-rw-r--r-- | sshuttle/methods/nft.py | 45 |
2 files changed, 54 insertions, 17 deletions
diff --git a/sshuttle/methods/__init__.py b/sshuttle/methods/__init__.py index 7d774e1..2c59904 100644 --- a/sshuttle/methods/__init__.py +++ b/sshuttle/methods/__init__.py @@ -2,24 +2,34 @@ import importlib import socket import struct import errno +import ipaddress from sshuttle.helpers import Fatal, debug3, which def original_dst(sock): + ip = "0.0.0.0" + port = -1 try: + family = sock.family SO_ORIGINAL_DST = 80 - SOCKADDR_MIN = 16 - sockaddr_in = sock.getsockopt(socket.SOL_IP, - SO_ORIGINAL_DST, SOCKADDR_MIN) - (proto, port, a, b, c, d) = struct.unpack('!HHBBBB', sockaddr_in[:8]) - # FIXME: decoding is IPv4 only. - assert(socket.htons(proto) == socket.AF_INET) - ip = '%d.%d.%d.%d' % (a, b, c, d) - return (ip, port) + + if family == socket.AF_INET: + SOCKADDR_MIN = 16 + sockaddr_in = sock.getsockopt(socket.SOL_IP, + SO_ORIGINAL_DST, SOCKADDR_MIN) + port, raw_ip = struct.unpack_from('!2xH4s', sockaddr_in[:8]) + ip = str(ipaddress.IPv4Address(raw_ip)) + elif family == socket.AF_INET6: + sockaddr_in = sock.getsockopt(41, SO_ORIGINAL_DST, 64) + port, raw_ip = struct.unpack_from("!2xH4x16s", sockaddr_in) + ip = str(ipaddress.IPv6Address(raw_ip)) + else: + raise Fatal("fw: Unknown family type.") except socket.error as e: if e.args[0] == errno.ENOPROTOOPT: return sock.getsockname() raise + return (ip, port) class Features(object): diff --git a/sshuttle/methods/nft.py b/sshuttle/methods/nft.py index 3ec47e0..058baa9 100644 --- a/sshuttle/methods/nft.py +++ b/sshuttle/methods/nft.py @@ -16,7 +16,10 @@ class Method(BaseMethod): if udp: raise Exception("UDP not supported by nft") - table = 'sshuttle-%s' % port + if family == socket.AF_INET: + table = 'sshuttle-ipv4-%s' % port + if family == socket.AF_INET6: + table = 'sshuttle-ipv6-%s' % port def _nft(action, *args): return nft(family, table, action, *args) @@ -37,7 +40,10 @@ class Method(BaseMethod): # This TTL hack allows the client and server to run on the # same host. The connections the sshuttle server makes will # have TTL set to 63. - _nft('add rule', chain, 'ip ttl == 63 return') + if family == socket.AF_INET: + _nft('add rule', chain, 'ip ttl == 63 return') + elif family == socket.AF_INET6: + _nft('add rule', chain, 'ip6 hoplimit == 63 return') # Redirect DNS traffic as requested. This includes routing traffic # to localhost DNS servers through sshuttle. @@ -57,7 +63,11 @@ class Method(BaseMethod): # create new subnet entries. for _, swidth, sexclude, snet, fport, lport \ in sorted(subnets, key=subnet_weight, reverse=True): - tcp_ports = ('ip', 'protocol', 'tcp') + if family == socket.AF_INET: + tcp_ports = ('ip', 'protocol', 'tcp') + elif family == socket.AF_INET6: + tcp_ports = ('ip6', 'nexthdr', 'tcp') + if fport and fport != lport: tcp_ports = \ tcp_ports + \ @@ -66,21 +76,38 @@ class Method(BaseMethod): tcp_ports = tcp_ports + ('tcp', 'dport', '%d' % (fport)) if sexclude: - _nft('add rule', chain, *(tcp_ports + ( - 'ip daddr %s/%s' % (snet, swidth), 'return'))) + if family == socket.AF_INET: + _nft('add rule', chain, *(tcp_ports + ( + 'ip daddr %s/%s' % (snet, swidth), 'return'))) + elif family == socket.AF_INET6: + _nft('add rule', chain, *(tcp_ports + ( + 'ip6 daddr %s/%s' % (snet, swidth), 'return'))) else: - _nft('add rule', chain, *(tcp_ports + ( - 'ip daddr %s/%s' % (snet, swidth), - ('redirect to :' + str(port))))) + if family == socket.AF_INET: + _nft('add rule', chain, *(tcp_ports + ( + 'ip daddr %s/%s' % (snet, swidth), + ('redirect to :' + str(port))))) + elif family == socket.AF_INET6: + _nft('add rule', chain, *(tcp_ports + ( + 'ip6 daddr %s/%s' % (snet, swidth), + ('redirect to :' + str(port))))) def restore_firewall(self, port, family, udp, user): if udp: raise Exception("UDP not supported by nft method_name") - table = 'sshuttle-%s' % port + if family == socket.AF_INET: + table = 'sshuttle-ipv4-%s' % port + if family == socket.AF_INET6: + table = 'sshuttle-ipv6-%s' % port def _nft(action, *args): return nft(family, table, action, *args) # basic cleanup/setup of chains nonfatal(_nft, 'delete table', '') + + def get_supported_features(self): + result = super(Method, self).get_supported_features() + result.ipv6 = True + return result |