2015-11-16 23:19:20 +01:00
|
|
|
import io
|
2022-05-19 15:41:27 +02:00
|
|
|
import os
|
2017-09-24 14:11:26 +02:00
|
|
|
from socket import AF_INET, AF_INET6
|
2015-11-16 23:19:20 +01:00
|
|
|
|
2021-01-16 01:59:28 +01:00
|
|
|
from unittest.mock import Mock, patch, call
|
2022-05-19 15:41:27 +02:00
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
2015-11-16 23:19:20 +01:00
|
|
|
import sshuttle.firewall
|
|
|
|
|
|
|
|
|
|
|
|
def setup_daemon():
|
2024-01-01 19:54:31 +01:00
|
|
|
stdin = io.BytesIO(u"""ROUTES
|
2017-09-24 14:11:26 +02:00
|
|
|
{inet},24,0,1.2.3.0,8000,9000
|
|
|
|
{inet},32,1,1.2.3.66,8080,8080
|
|
|
|
{inet6},64,0,2404:6800:4004:80c::,0,0
|
|
|
|
{inet6},128,1,2404:6800:4004:80c::101f,80,80
|
2015-11-16 23:19:20 +01:00
|
|
|
NSLIST
|
2017-09-24 14:11:26 +02:00
|
|
|
{inet},1.2.3.33
|
|
|
|
{inet6},2404:6800:4004:80c::33
|
2015-11-16 23:19:20 +01:00
|
|
|
PORTS 1024,1025,1026,1027
|
2023-08-04 14:59:33 +02:00
|
|
|
GO 1 - - 0x01 12345
|
2015-12-06 01:02:31 +01:00
|
|
|
HOST 1.2.3.3,existing
|
2024-01-01 21:01:24 +01:00
|
|
|
""".format(inet=AF_INET, inet6=AF_INET6).encode('ASCII'))
|
2015-11-16 23:19:20 +01:00
|
|
|
stdout = Mock()
|
|
|
|
return stdin, stdout
|
|
|
|
|
|
|
|
|
2015-12-06 01:02:31 +01:00
|
|
|
def test_rewrite_etc_hosts(tmpdir):
|
|
|
|
orig_hosts = tmpdir.join("hosts.orig")
|
|
|
|
orig_hosts.write("1.2.3.3 existing\n")
|
2015-11-16 23:19:20 +01:00
|
|
|
|
2015-12-06 01:02:31 +01:00
|
|
|
new_hosts = tmpdir.join("hosts")
|
|
|
|
orig_hosts.copy(new_hosts)
|
2015-11-16 23:19:20 +01:00
|
|
|
|
2015-12-06 01:02:31 +01:00
|
|
|
hostmap = {
|
|
|
|
'myhost': '1.2.3.4',
|
|
|
|
'myotherhost': '1.2.3.5',
|
|
|
|
}
|
|
|
|
with patch('sshuttle.firewall.HOSTSFILE', new=str(new_hosts)):
|
|
|
|
sshuttle.firewall.rewrite_etc_hosts(hostmap, 10)
|
2015-11-16 23:19:20 +01:00
|
|
|
|
2015-12-06 01:02:31 +01:00
|
|
|
with new_hosts.open() as f:
|
2015-11-16 23:39:53 +01:00
|
|
|
line = f.readline()
|
2015-11-16 23:19:20 +01:00
|
|
|
s = line.split()
|
|
|
|
assert s == ['1.2.3.3', 'existing']
|
|
|
|
|
2015-11-16 23:39:53 +01:00
|
|
|
line = f.readline()
|
2015-11-16 23:19:20 +01:00
|
|
|
s = line.split()
|
|
|
|
assert s == ['1.2.3.4', 'myhost',
|
|
|
|
'#', 'sshuttle-firewall-10', 'AUTOCREATED']
|
|
|
|
|
2015-11-16 23:39:53 +01:00
|
|
|
line = f.readline()
|
2015-11-16 23:19:20 +01:00
|
|
|
s = line.split()
|
|
|
|
assert s == ['1.2.3.5', 'myotherhost',
|
|
|
|
'#', 'sshuttle-firewall-10', 'AUTOCREATED']
|
|
|
|
|
2015-11-16 23:39:53 +01:00
|
|
|
line = f.readline()
|
|
|
|
assert line == ""
|
2015-11-16 23:19:20 +01:00
|
|
|
|
2015-12-06 01:02:31 +01:00
|
|
|
with patch('sshuttle.firewall.HOSTSFILE', new=str(new_hosts)):
|
2020-10-19 06:17:37 +02:00
|
|
|
sshuttle.firewall.restore_etc_hosts(hostmap, 10)
|
2015-12-06 01:02:31 +01:00
|
|
|
assert orig_hosts.computehash() == new_hosts.computehash()
|
2015-11-16 23:19:20 +01:00
|
|
|
|
|
|
|
|
2022-05-19 15:41:27 +02:00
|
|
|
@patch('os.link')
|
|
|
|
@patch('os.rename')
|
|
|
|
def test_rewrite_etc_hosts_no_overwrite(mock_link, mock_rename, tmpdir):
|
|
|
|
mock_link.side_effect = OSError
|
|
|
|
mock_rename.side_effect = OSError
|
|
|
|
|
|
|
|
with pytest.raises(OSError):
|
|
|
|
os.link('/test_from', '/test_to')
|
|
|
|
|
|
|
|
with pytest.raises(OSError):
|
|
|
|
os.rename('/test_from', '/test_to')
|
|
|
|
|
|
|
|
test_rewrite_etc_hosts(tmpdir)
|
|
|
|
|
|
|
|
|
2017-05-01 18:52:08 +02:00
|
|
|
def test_subnet_weight():
|
|
|
|
subnets = [
|
2017-09-24 14:11:26 +02:00
|
|
|
(AF_INET, 16, 0, '192.168.0.0', 0, 0),
|
|
|
|
(AF_INET, 24, 0, '192.168.69.0', 0, 0),
|
|
|
|
(AF_INET, 32, 0, '192.168.69.70', 0, 0),
|
|
|
|
(AF_INET, 32, 1, '192.168.69.70', 0, 0),
|
|
|
|
(AF_INET, 32, 1, '192.168.69.70', 80, 80),
|
|
|
|
(AF_INET, 0, 1, '0.0.0.0', 0, 0),
|
|
|
|
(AF_INET, 0, 1, '0.0.0.0', 8000, 9000),
|
|
|
|
(AF_INET, 0, 1, '0.0.0.0', 8000, 8500),
|
|
|
|
(AF_INET, 0, 1, '0.0.0.0', 8000, 8000),
|
|
|
|
(AF_INET, 0, 1, '0.0.0.0', 400, 450)
|
2017-05-01 18:52:08 +02:00
|
|
|
]
|
|
|
|
subnets_sorted = [
|
2017-09-24 14:11:26 +02:00
|
|
|
(AF_INET, 32, 1, '192.168.69.70', 80, 80),
|
|
|
|
(AF_INET, 0, 1, '0.0.0.0', 8000, 8000),
|
|
|
|
(AF_INET, 0, 1, '0.0.0.0', 400, 450),
|
|
|
|
(AF_INET, 0, 1, '0.0.0.0', 8000, 8500),
|
|
|
|
(AF_INET, 0, 1, '0.0.0.0', 8000, 9000),
|
|
|
|
(AF_INET, 32, 1, '192.168.69.70', 0, 0),
|
|
|
|
(AF_INET, 32, 0, '192.168.69.70', 0, 0),
|
|
|
|
(AF_INET, 24, 0, '192.168.69.0', 0, 0),
|
|
|
|
(AF_INET, 16, 0, '192.168.0.0', 0, 0),
|
|
|
|
(AF_INET, 0, 1, '0.0.0.0', 0, 0)
|
2017-05-01 18:52:08 +02:00
|
|
|
]
|
2017-11-07 02:20:24 +01:00
|
|
|
|
2019-02-10 23:59:13 +01:00
|
|
|
assert subnets_sorted == sorted(subnets,
|
|
|
|
key=sshuttle.firewall.subnet_weight,
|
|
|
|
reverse=True)
|
2017-05-01 18:52:08 +02:00
|
|
|
|
|
|
|
|
2015-12-06 01:02:31 +01:00
|
|
|
@patch('sshuttle.firewall.rewrite_etc_hosts')
|
2015-11-16 23:32:40 +01:00
|
|
|
@patch('sshuttle.firewall.setup_daemon')
|
|
|
|
@patch('sshuttle.firewall.get_method')
|
2015-12-06 01:02:31 +01:00
|
|
|
def test_main(mock_get_method, mock_setup_daemon, mock_rewrite_etc_hosts):
|
2015-11-16 23:32:40 +01:00
|
|
|
stdin, stdout = setup_daemon()
|
|
|
|
mock_setup_daemon.return_value = stdin, stdout
|
|
|
|
|
2015-12-06 01:02:31 +01:00
|
|
|
mock_get_method("not_auto").name = "test"
|
|
|
|
mock_get_method.reset_mock()
|
2015-11-17 02:46:35 +01:00
|
|
|
|
2021-06-01 05:33:55 +02:00
|
|
|
sshuttle.firewall.main("not_auto", False)
|
2015-11-16 23:32:40 +01:00
|
|
|
|
2015-12-06 01:02:31 +01:00
|
|
|
assert mock_rewrite_etc_hosts.mock_calls == [
|
|
|
|
call({'1.2.3.3': 'existing'}, 1024),
|
|
|
|
call({}, 1024),
|
|
|
|
]
|
2015-11-17 02:46:35 +01:00
|
|
|
|
2015-12-06 01:02:31 +01:00
|
|
|
assert stdout.mock_calls == [
|
2024-01-01 19:54:31 +01:00
|
|
|
call.write(b'READY test\n'),
|
2015-11-16 23:32:40 +01:00
|
|
|
call.flush(),
|
2024-01-01 19:54:31 +01:00
|
|
|
call.write(b'STARTED\n'),
|
2015-11-16 23:32:40 +01:00
|
|
|
call.flush()
|
|
|
|
]
|
2015-12-06 01:02:31 +01:00
|
|
|
assert mock_setup_daemon.mock_calls == [call()]
|
|
|
|
assert mock_get_method.mock_calls == [
|
|
|
|
call('not_auto'),
|
2020-12-26 21:25:33 +01:00
|
|
|
call().is_supported(),
|
|
|
|
call().is_supported().__bool__(),
|
2015-11-16 23:32:40 +01:00
|
|
|
call().setup_firewall(
|
|
|
|
1024, 1026,
|
2017-09-24 14:11:26 +02:00
|
|
|
[(AF_INET6, u'2404:6800:4004:80c::33')],
|
|
|
|
AF_INET6,
|
|
|
|
[(AF_INET6, 64, False, u'2404:6800:4004:80c::', 0, 0),
|
2022-05-19 15:41:27 +02:00
|
|
|
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 80, 80)],
|
2017-09-08 03:17:37 +02:00
|
|
|
True,
|
2021-01-18 21:28:52 +01:00
|
|
|
None,
|
2023-08-04 14:51:03 +02:00
|
|
|
None,
|
2021-06-01 05:33:55 +02:00
|
|
|
'0x01'),
|
2015-11-16 23:32:40 +01:00
|
|
|
call().setup_firewall(
|
|
|
|
1025, 1027,
|
2017-09-24 14:11:26 +02:00
|
|
|
[(AF_INET, u'1.2.3.33')],
|
|
|
|
AF_INET,
|
|
|
|
[(AF_INET, 24, False, u'1.2.3.0', 8000, 9000),
|
2022-05-19 15:41:27 +02:00
|
|
|
(AF_INET, 32, True, u'1.2.3.66', 8080, 8080)],
|
2017-09-08 03:17:37 +02:00
|
|
|
True,
|
2021-01-18 21:28:52 +01:00
|
|
|
None,
|
2023-08-04 14:51:03 +02:00
|
|
|
None,
|
2021-06-01 05:33:55 +02:00
|
|
|
'0x01'),
|
2022-09-07 08:56:21 +02:00
|
|
|
call().wait_for_firewall_ready(),
|
2023-08-04 14:51:03 +02:00
|
|
|
call().restore_firewall(1024, AF_INET6, True, None, None),
|
|
|
|
call().restore_firewall(1025, AF_INET, True, None, None),
|
2015-11-16 23:32:40 +01:00
|
|
|
]
|