Skip to content

Commit e3a1c56

Browse files
committed
Add more methods tests.
Fix bug in tproxy recv_udp() method.
1 parent 99050aa commit e3a1c56

File tree

3 files changed

+423
-1
lines changed

3 files changed

+423
-1
lines changed

sshuttle/methods/tproxy.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,14 @@ def recv_udp(self, udp_listener, bufsize):
118118
"-- ignored UDP from %r: "
119119
"couldn't determine destination IP address\n" % (srcip,))
120120
return None
121-
return None
121+
return srcip, dstip, data
122122

123123
def send_udp(self, sock, srcip, dstip, data):
124+
if not srcip:
125+
debug1(
126+
"-- ignored UDP to %r: "
127+
"couldn't determine source IP address\n" % (dstip,))
128+
return
124129
sender = socket.socket(sock.family, socket.SOCK_DGRAM)
125130
sender.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
126131
sender.setsockopt(socket.SOL_IP, IP_TRANSPARENT, 1)

sshuttle/tests/test_methods_nat.py

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import pytest
2+
from mock import Mock, patch, call
3+
import socket
4+
import struct
5+
6+
from sshuttle.methods import get_method
7+
8+
9+
def test_get_supported_features():
10+
method = get_method('nat')
11+
features = method.get_supported_features()
12+
assert not features.ipv6
13+
assert not features.udp
14+
15+
16+
def test_get_tcp_dstip():
17+
sock = Mock()
18+
sock.getsockopt.return_value = struct.pack(
19+
'!HHBBBB', socket.ntohs(socket.AF_INET), 1024, 127, 0, 0, 1)
20+
method = get_method('nat')
21+
assert method.get_tcp_dstip(sock) == ('127.0.0.1', 1024)
22+
assert sock.mock_calls == [call.getsockopt(0, 80, 16)]
23+
24+
25+
def test_recv_udp():
26+
sock = Mock()
27+
sock.recvfrom.return_value = "11111", "127.0.0.1"
28+
method = get_method('nat')
29+
result = method.recv_udp(sock, 1024)
30+
assert sock.mock_calls == [call.recvfrom(1024)]
31+
assert result == ("127.0.0.1", None, "11111")
32+
33+
34+
def test_send_udp():
35+
sock = Mock()
36+
method = get_method('nat')
37+
method.send_udp(sock, None, "127.0.0.1", "22222")
38+
assert sock.mock_calls == [call.sendto("22222", "127.0.0.1")]
39+
40+
41+
def test_setup_tcp_listener():
42+
listener = Mock()
43+
method = get_method('nat')
44+
method.setup_tcp_listener(listener)
45+
assert listener.mock_calls == []
46+
47+
48+
def test_setup_udp_listener():
49+
listener = Mock()
50+
method = get_method('nat')
51+
method.setup_udp_listener(listener)
52+
assert listener.mock_calls == []
53+
54+
55+
def test_check_settings():
56+
method = get_method('nat')
57+
method.check_settings(True, True)
58+
method.check_settings(False, True)
59+
60+
61+
def test_firewall_command():
62+
method = get_method('nat')
63+
assert not method.firewall_command("somthing")
64+
65+
66+
@patch('sshuttle.methods.nat.ipt')
67+
@patch('sshuttle.methods.nat.ipt_ttl')
68+
@patch('sshuttle.methods.nat.ipt_chain_exists')
69+
def test_setup_firewall(mock_ipt_chain_exists, mock_ipt_ttl, mock_ipt):
70+
mock_ipt_chain_exists.return_value = True
71+
method = get_method('nat')
72+
assert method.name == 'nat'
73+
74+
with pytest.raises(Exception) as excinfo:
75+
method.setup_firewall(
76+
1024, 1026,
77+
[(10, u'2404:6800:4004:80c::33')],
78+
10,
79+
[(10, 64, False, u'2404:6800:4004:80c::'),
80+
(10, 128, True, u'2404:6800:4004:80c::101f')],
81+
True)
82+
assert str(excinfo.value) \
83+
== 'Address family "AF_INET6" unsupported by nat method_name'
84+
assert mock_ipt_chain_exists.mock_calls == []
85+
assert mock_ipt_ttl.mock_calls == []
86+
assert mock_ipt.mock_calls == []
87+
88+
with pytest.raises(Exception) as excinfo:
89+
method.setup_firewall(
90+
1025, 1027,
91+
[(2, u'1.2.3.33')],
92+
2,
93+
[(2, 24, False, u'1.2.3.0'), (2, 32, True, u'1.2.3.66')],
94+
True)
95+
assert str(excinfo.value) == 'UDP not supported by nat method_name'
96+
assert mock_ipt_chain_exists.mock_calls == []
97+
assert mock_ipt_ttl.mock_calls == []
98+
assert mock_ipt.mock_calls == []
99+
100+
method.setup_firewall(
101+
1025, 1027,
102+
[(2, u'1.2.3.33')],
103+
2,
104+
[(2, 24, False, u'1.2.3.0'), (2, 32, True, u'1.2.3.66')],
105+
False)
106+
assert mock_ipt_chain_exists.mock_calls == [
107+
call(2, 'nat', 'sshuttle-1025')
108+
]
109+
assert mock_ipt_ttl.mock_calls == [
110+
call(2, 'nat', '-A', 'sshuttle-1025', '-j', 'REDIRECT',
111+
'--dest', u'1.2.3.0/24', '-p', 'tcp', '--to-ports', '1025'),
112+
call(2, 'nat', '-A', 'sshuttle-1025', '-j', 'REDIRECT',
113+
'--dest', u'1.2.3.33/32', '-p', 'udp',
114+
'--dport', '53', '--to-ports', '1027')
115+
]
116+
assert mock_ipt.mock_calls == [
117+
call(2, 'nat', '-D', 'OUTPUT', '-j', 'sshuttle-1025'),
118+
call(2, 'nat', '-D', 'PREROUTING', '-j', 'sshuttle-1025'),
119+
call(2, 'nat', '-F', 'sshuttle-1025'),
120+
call(2, 'nat', '-X', 'sshuttle-1025'),
121+
call(2, 'nat', '-N', 'sshuttle-1025'),
122+
call(2, 'nat', '-F', 'sshuttle-1025'),
123+
call(2, 'nat', '-I', 'OUTPUT', '1', '-j', 'sshuttle-1025'),
124+
call(2, 'nat', '-I', 'PREROUTING', '1', '-j', 'sshuttle-1025'),
125+
call(2, 'nat', '-A', 'sshuttle-1025', '-j', 'RETURN',
126+
'--dest', u'1.2.3.66/32', '-p', 'tcp')
127+
]
128+
mock_ipt_chain_exists.reset_mock()
129+
mock_ipt_ttl.reset_mock()
130+
mock_ipt.reset_mock()
131+
132+
method.setup_firewall(1025, 0, [], 2, [], False)
133+
assert mock_ipt_chain_exists.mock_calls == [
134+
call(2, 'nat', 'sshuttle-1025')
135+
]
136+
assert mock_ipt_ttl.mock_calls == []
137+
assert mock_ipt.mock_calls == [
138+
call(2, 'nat', '-D', 'OUTPUT', '-j', 'sshuttle-1025'),
139+
call(2, 'nat', '-D', 'PREROUTING', '-j', 'sshuttle-1025'),
140+
call(2, 'nat', '-F', 'sshuttle-1025'),
141+
call(2, 'nat', '-X', 'sshuttle-1025')
142+
]
143+
mock_ipt_chain_exists.reset_mock()
144+
mock_ipt_ttl.reset_mock()
145+
mock_ipt.reset_mock()

0 commit comments

Comments
 (0)