mirror of
https://github.com/sshuttle/sshuttle.git
synced 2025-02-16 10:29:36 +01:00
Remove references to legacy PyXAPI socket_ext for recvmsg
socket.recvmsg has been in Python since version 3.3 and we don't support anything older then 3.6 the server side.
This commit is contained in:
parent
fca9bd6478
commit
b896a4b7f3
@ -40,11 +40,11 @@ Linux with TPROXY method
|
|||||||
Supports:
|
Supports:
|
||||||
|
|
||||||
* IPv4 TCP
|
* IPv4 TCP
|
||||||
* IPv4 UDP (requires ``recvmsg`` - see below)
|
* IPv4 UDP
|
||||||
* IPv6 DNS (requires ``recvmsg`` - see below)
|
* IPv6 DNS
|
||||||
* IPv6 TCP
|
* IPv6 TCP
|
||||||
* IPv6 UDP (requires ``recvmsg`` - see below)
|
* IPv6 UDP
|
||||||
* IPv6 DNS (requires ``recvmsg`` - see below)
|
* IPv6 DNS
|
||||||
|
|
||||||
|
|
||||||
MacOS / FreeBSD / OpenBSD / pfSense
|
MacOS / FreeBSD / OpenBSD / pfSense
|
||||||
|
@ -22,19 +22,7 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
getpwnam = None
|
getpwnam = None
|
||||||
|
|
||||||
try:
|
import socket
|
||||||
# try getting recvmsg from python
|
|
||||||
import socket as pythonsocket
|
|
||||||
getattr(pythonsocket.socket, "recvmsg")
|
|
||||||
socket = pythonsocket
|
|
||||||
except AttributeError:
|
|
||||||
# try getting recvmsg from socket_ext library
|
|
||||||
try:
|
|
||||||
import socket_ext
|
|
||||||
getattr(socket_ext.socket, "recvmsg")
|
|
||||||
socket = socket_ext
|
|
||||||
except ImportError:
|
|
||||||
import socket
|
|
||||||
|
|
||||||
_extra_fd = os.open(os.devnull, os.O_RDONLY)
|
_extra_fd = os.open(os.devnull, os.O_RDONLY)
|
||||||
|
|
||||||
|
@ -4,59 +4,26 @@ from sshuttle.methods import BaseMethod
|
|||||||
from sshuttle.helpers import log, debug1, debug2, debug3, \
|
from sshuttle.helpers import log, debug1, debug2, debug3, \
|
||||||
Fatal, family_to_string, get_env, which
|
Fatal, family_to_string, get_env, which
|
||||||
|
|
||||||
recvmsg = None
|
import socket
|
||||||
try:
|
|
||||||
# try getting recvmsg from python
|
|
||||||
import socket as pythonsocket
|
|
||||||
getattr(pythonsocket.socket, "recvmsg")
|
|
||||||
socket = pythonsocket
|
|
||||||
recvmsg = "python"
|
|
||||||
except AttributeError:
|
|
||||||
# try getting recvmsg from socket_ext library
|
|
||||||
try:
|
|
||||||
import socket_ext
|
|
||||||
getattr(socket_ext.socket, "recvmsg")
|
|
||||||
socket = socket_ext
|
|
||||||
recvmsg = "socket_ext"
|
|
||||||
except ImportError:
|
|
||||||
import socket
|
|
||||||
|
|
||||||
IP_BINDANY = 24
|
IP_BINDANY = 24
|
||||||
IP_RECVDSTADDR = 7
|
IP_RECVDSTADDR = 7
|
||||||
SOL_IPV6 = 41
|
SOL_IPV6 = 41
|
||||||
IPV6_RECVDSTADDR = 74
|
IPV6_RECVDSTADDR = 74
|
||||||
|
|
||||||
if recvmsg == "python":
|
|
||||||
def recv_udp(listener, bufsize):
|
def recv_udp(listener, bufsize):
|
||||||
debug3('Accept UDP python using recvmsg.')
|
debug3('Accept UDP python using recvmsg.')
|
||||||
data, ancdata, _, srcip = listener.recvmsg(4096,
|
data, ancdata, _, srcip = listener.recvmsg(4096,
|
||||||
socket.CMSG_SPACE(4))
|
socket.CMSG_SPACE(4))
|
||||||
dstip = None
|
dstip = None
|
||||||
for cmsg_level, cmsg_type, cmsg_data in ancdata:
|
for cmsg_level, cmsg_type, cmsg_data in ancdata:
|
||||||
if cmsg_level == socket.SOL_IP and cmsg_type == IP_RECVDSTADDR:
|
if cmsg_level == socket.SOL_IP and cmsg_type == IP_RECVDSTADDR:
|
||||||
port = 53
|
port = 53
|
||||||
ip = socket.inet_ntop(socket.AF_INET, cmsg_data[0:4])
|
ip = socket.inet_ntop(socket.AF_INET, cmsg_data[0:4])
|
||||||
dstip = (ip, port)
|
dstip = (ip, port)
|
||||||
break
|
break
|
||||||
return (srcip, dstip, data)
|
return (srcip, dstip, data)
|
||||||
elif recvmsg == "socket_ext":
|
|
||||||
def recv_udp(listener, bufsize):
|
|
||||||
debug3('Accept UDP using socket_ext recvmsg.')
|
|
||||||
srcip, data, adata, _ = listener.recvmsg((bufsize,),
|
|
||||||
socket.CMSG_SPACE(4))
|
|
||||||
dstip = None
|
|
||||||
for a in adata:
|
|
||||||
if a.cmsg_level == socket.SOL_IP and a.cmsg_type == IP_RECVDSTADDR:
|
|
||||||
port = 53
|
|
||||||
ip = socket.inet_ntop(socket.AF_INET, a.cmsg_data[0:4])
|
|
||||||
dstip = (ip, port)
|
|
||||||
break
|
|
||||||
return (srcip, dstip, data[0])
|
|
||||||
else:
|
|
||||||
def recv_udp(listener, bufsize):
|
|
||||||
debug3('Accept UDP using recvfrom.')
|
|
||||||
data, srcip = listener.recvfrom(bufsize)
|
|
||||||
return (srcip, None, data)
|
|
||||||
|
|
||||||
|
|
||||||
def ipfw_rule_exists(n):
|
def ipfw_rule_exists(n):
|
||||||
|
@ -5,22 +5,7 @@ from sshuttle.linux import ipt, ipt_chain_exists
|
|||||||
from sshuttle.methods import BaseMethod
|
from sshuttle.methods import BaseMethod
|
||||||
from sshuttle.helpers import debug1, debug2, debug3, Fatal, which
|
from sshuttle.helpers import debug1, debug2, debug3, Fatal, which
|
||||||
|
|
||||||
recvmsg = None
|
import socket
|
||||||
try:
|
|
||||||
# try getting recvmsg from python
|
|
||||||
import socket as pythonsocket
|
|
||||||
getattr(pythonsocket.socket, "recvmsg")
|
|
||||||
socket = pythonsocket
|
|
||||||
recvmsg = "python"
|
|
||||||
except AttributeError:
|
|
||||||
# try getting recvmsg from socket_ext library
|
|
||||||
try:
|
|
||||||
import socket_ext
|
|
||||||
getattr(socket_ext.socket, "recvmsg")
|
|
||||||
socket = socket_ext
|
|
||||||
recvmsg = "socket_ext"
|
|
||||||
except ImportError:
|
|
||||||
import socket
|
|
||||||
|
|
||||||
|
|
||||||
IP_TRANSPARENT = 19
|
IP_TRANSPARENT = 19
|
||||||
@ -30,75 +15,37 @@ SOL_IPV6 = 41
|
|||||||
IPV6_ORIGDSTADDR = 74
|
IPV6_ORIGDSTADDR = 74
|
||||||
IPV6_RECVORIGDSTADDR = IPV6_ORIGDSTADDR
|
IPV6_RECVORIGDSTADDR = IPV6_ORIGDSTADDR
|
||||||
|
|
||||||
if recvmsg == "python":
|
|
||||||
def recv_udp(listener, bufsize):
|
def recv_udp(listener, bufsize):
|
||||||
debug3('Accept UDP python using recvmsg.')
|
debug3('Accept UDP python using recvmsg.')
|
||||||
data, ancdata, _, srcip = listener.recvmsg(
|
data, ancdata, _, srcip = listener.recvmsg(
|
||||||
4096, socket.CMSG_SPACE(24))
|
4096, socket.CMSG_SPACE(24))
|
||||||
dstip = None
|
dstip = None
|
||||||
family = None
|
family = None
|
||||||
for cmsg_level, cmsg_type, cmsg_data in ancdata:
|
for cmsg_level, cmsg_type, cmsg_data in ancdata:
|
||||||
if cmsg_level == socket.SOL_IP and cmsg_type == IP_ORIGDSTADDR:
|
if cmsg_level == socket.SOL_IP and cmsg_type == IP_ORIGDSTADDR:
|
||||||
family, port = struct.unpack('=HH', cmsg_data[0:4])
|
family, port = struct.unpack('=HH', cmsg_data[0:4])
|
||||||
port = socket.htons(port)
|
port = socket.htons(port)
|
||||||
if family == socket.AF_INET:
|
if family == socket.AF_INET:
|
||||||
start = 4
|
start = 4
|
||||||
length = 4
|
length = 4
|
||||||
else:
|
else:
|
||||||
raise Fatal("Unsupported socket type '%s'" % family)
|
raise Fatal("Unsupported socket type '%s'" % family)
|
||||||
ip = socket.inet_ntop(family, cmsg_data[start:start + length])
|
ip = socket.inet_ntop(family, cmsg_data[start:start + length])
|
||||||
dstip = (ip, port)
|
dstip = (ip, port)
|
||||||
break
|
break
|
||||||
elif cmsg_level == SOL_IPV6 and cmsg_type == IPV6_ORIGDSTADDR:
|
elif cmsg_level == SOL_IPV6 and cmsg_type == IPV6_ORIGDSTADDR:
|
||||||
family, port = struct.unpack('=HH', cmsg_data[0:4])
|
family, port = struct.unpack('=HH', cmsg_data[0:4])
|
||||||
port = socket.htons(port)
|
port = socket.htons(port)
|
||||||
if family == socket.AF_INET6:
|
if family == socket.AF_INET6:
|
||||||
start = 8
|
start = 8
|
||||||
length = 16
|
length = 16
|
||||||
else:
|
else:
|
||||||
raise Fatal("Unsupported socket type '%s'" % family)
|
raise Fatal("Unsupported socket type '%s'" % family)
|
||||||
ip = socket.inet_ntop(family, cmsg_data[start:start + length])
|
ip = socket.inet_ntop(family, cmsg_data[start:start + length])
|
||||||
dstip = (ip, port)
|
dstip = (ip, port)
|
||||||
break
|
break
|
||||||
return (srcip, dstip, data)
|
return (srcip, dstip, data)
|
||||||
elif recvmsg == "socket_ext":
|
|
||||||
def recv_udp(listener, bufsize):
|
|
||||||
debug3('Accept UDP using socket_ext recvmsg.')
|
|
||||||
srcip, data, adata, _ = listener.recvmsg(
|
|
||||||
(bufsize,), socket.CMSG_SPACE(24))
|
|
||||||
dstip = None
|
|
||||||
family = None
|
|
||||||
for a in adata:
|
|
||||||
if a.cmsg_level == socket.SOL_IP and a.cmsg_type == IP_ORIGDSTADDR:
|
|
||||||
family, port = struct.unpack('=HH', a.cmsg_data[0:4])
|
|
||||||
port = socket.htons(port)
|
|
||||||
if family == socket.AF_INET:
|
|
||||||
start = 4
|
|
||||||
length = 4
|
|
||||||
else:
|
|
||||||
raise Fatal("Unsupported socket type '%s'" % family)
|
|
||||||
ip = socket.inet_ntop(
|
|
||||||
family, a.cmsg_data[start:start + length])
|
|
||||||
dstip = (ip, port)
|
|
||||||
break
|
|
||||||
elif a.cmsg_level == SOL_IPV6 and a.cmsg_type == IPV6_ORIGDSTADDR:
|
|
||||||
family, port = struct.unpack('=HH', a.cmsg_data[0:4])
|
|
||||||
port = socket.htons(port)
|
|
||||||
if family == socket.AF_INET6:
|
|
||||||
start = 8
|
|
||||||
length = 16
|
|
||||||
else:
|
|
||||||
raise Fatal("Unsupported socket type '%s'" % family)
|
|
||||||
ip = socket.inet_ntop(
|
|
||||||
family, a.cmsg_data[start:start + length])
|
|
||||||
dstip = (ip, port)
|
|
||||||
break
|
|
||||||
return (srcip, dstip, data[0])
|
|
||||||
else:
|
|
||||||
def recv_udp(listener, bufsize):
|
|
||||||
debug3('Accept UDP using recvfrom.')
|
|
||||||
data, srcip = listener.recvfrom(bufsize)
|
|
||||||
return (srcip, None, data)
|
|
||||||
|
|
||||||
|
|
||||||
class Method(BaseMethod):
|
class Method(BaseMethod):
|
||||||
@ -106,12 +53,8 @@ class Method(BaseMethod):
|
|||||||
def get_supported_features(self):
|
def get_supported_features(self):
|
||||||
result = super(Method, self).get_supported_features()
|
result = super(Method, self).get_supported_features()
|
||||||
result.ipv6 = True
|
result.ipv6 = True
|
||||||
if recvmsg is None:
|
result.udp = True
|
||||||
result.udp = False
|
result.dns = True
|
||||||
result.dns = False
|
|
||||||
else:
|
|
||||||
result.udp = True
|
|
||||||
result.dns = True
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def get_tcp_dstip(self, sock):
|
def get_tcp_dstip(self, sock):
|
||||||
|
@ -6,8 +6,7 @@ from unittest.mock import Mock, patch, call
|
|||||||
from sshuttle.methods import get_method
|
from sshuttle.methods import get_method
|
||||||
|
|
||||||
|
|
||||||
@patch("sshuttle.methods.tproxy.recvmsg")
|
def test_get_supported_features():
|
||||||
def test_get_supported_features_recvmsg(mock_recvmsg):
|
|
||||||
method = get_method('tproxy')
|
method = get_method('tproxy')
|
||||||
features = method.get_supported_features()
|
features = method.get_supported_features()
|
||||||
assert features.ipv6
|
assert features.ipv6
|
||||||
@ -15,15 +14,6 @@ def test_get_supported_features_recvmsg(mock_recvmsg):
|
|||||||
assert features.dns
|
assert features.dns
|
||||||
|
|
||||||
|
|
||||||
@patch("sshuttle.methods.tproxy.recvmsg", None)
|
|
||||||
def test_get_supported_features_norecvmsg():
|
|
||||||
method = get_method('tproxy')
|
|
||||||
features = method.get_supported_features()
|
|
||||||
assert features.ipv6
|
|
||||||
assert not features.udp
|
|
||||||
assert not features.dns
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_tcp_dstip():
|
def test_get_tcp_dstip():
|
||||||
sock = Mock()
|
sock = Mock()
|
||||||
sock.getsockname.return_value = ('127.0.0.1', 1024)
|
sock.getsockname.return_value = ('127.0.0.1', 1024)
|
||||||
|
Loading…
Reference in New Issue
Block a user