mirror of
https://github.com/sshuttle/sshuttle.git
synced 2024-11-21 23:43:18 +01:00
Merge branch 'master' into nat-ipv6
This commit is contained in:
commit
3f201095ea
@ -50,6 +50,14 @@ if [ "$FILE_NAME" == "" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Verify that the resulting file name begins with /etc/sudoers.d
|
||||||
|
FILE_NAME="$(realpath "/etc/sudoers.d/$FILE_NAME")"
|
||||||
|
if [[ "$FILE_NAME" != "/etc/sudoers.d/"* ]] ; then
|
||||||
|
echo -n "Invalid sudoers filename: Final sudoers file "
|
||||||
|
echo "location ($FILE_NAME) does not begin with /etc/sudoers.d"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Make a temp file to hold the sudoers config
|
# Make a temp file to hold the sudoers config
|
||||||
umask 077
|
umask 077
|
||||||
TEMP_FILE=$(mktemp)
|
TEMP_FILE=$(mktemp)
|
||||||
@ -62,9 +70,9 @@ visudo_code=$?
|
|||||||
rm "$TEMP_FILE"
|
rm "$TEMP_FILE"
|
||||||
|
|
||||||
if [ $visudo_code -eq 0 ]; then
|
if [ $visudo_code -eq 0 ]; then
|
||||||
echo "$CONTENT" > "/etc/sudoers.d/$FILE_NAME"
|
echo "$CONTENT" > "$FILE_NAME"
|
||||||
chmod 0440 "/etc/sudoers.d/$FILE_NAME"
|
chmod 0440 "$FILE_NAME"
|
||||||
echo "The sudoers file /etc/sudoers.d/$FILE_NAME has been successfully created!"
|
echo "The sudoers file $FILE_NAME has been successfully created!"
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
|
165
docs/manpage.rst
165
docs/manpage.rst
@ -10,8 +10,8 @@ Synopsis
|
|||||||
Description
|
Description
|
||||||
-----------
|
-----------
|
||||||
:program:`sshuttle` allows you to create a VPN connection from your
|
:program:`sshuttle` allows you to create a VPN connection from your
|
||||||
machine to any remote server that you can connect to via
|
machine to any remote server that you can connect to via ssh, as long
|
||||||
ssh, as long as that server has python 3.6 or higher.
|
as that server has a sufficiently new Python installation.
|
||||||
|
|
||||||
To work, you must have root access on the local machine,
|
To work, you must have root access on the local machine,
|
||||||
but you can have a normal account on the server.
|
but you can have a normal account on the server.
|
||||||
@ -31,22 +31,23 @@ Options
|
|||||||
.. option:: <subnets>
|
.. option:: <subnets>
|
||||||
|
|
||||||
A list of subnets to route over the VPN, in the form
|
A list of subnets to route over the VPN, in the form
|
||||||
``a.b.c.d[/width][port[-port]]``. Valid examples are 1.2.3.4 (a
|
``a.b.c.d[/width][port[-port]]``. Valid examples are 1.2.3.4 (a
|
||||||
single IP address), 1.2.3.4/32 (equivalent to 1.2.3.4),
|
single IP address) and 1.2.3.4/32 (equivalent to 1.2.3.4),
|
||||||
1.2.3.0/24 (a 24-bit subnet, ie. with a 255.255.255.0
|
1.2.3.0/24 (a 24-bit subnet, ie. with a 255.255.255.0 netmask).
|
||||||
netmask), and 0/0 ('just route everything through the
|
Specify subnets 0/0 to match all IPv4 addresses and ::/0 to match
|
||||||
VPN'). Any of the previous examples are also valid if you append
|
all IPv6 addresses. Any of the previous examples are also valid if
|
||||||
a port or a port range, so 1.2.3.4:8000 will only tunnel traffic
|
you append a port or a port range, so 1.2.3.4:8000 will only
|
||||||
that has as the destination port 8000 of 1.2.3.4 and
|
tunnel traffic that has as the destination port 8000 of 1.2.3.4
|
||||||
1.2.3.0/24:8000-9000 will tunnel traffic going to any port between
|
and 1.2.3.0/24:8000-9000 will tunnel traffic going to any port
|
||||||
8000 and 9000 (inclusive) for all IPs in the 1.2.3.0/24 subnet.
|
between 8000 and 9000 (inclusive) for all IPs in the 1.2.3.0/24
|
||||||
A hostname can be provided instead of an IP address. If the
|
subnet. A hostname can be provided instead of an IP address. If
|
||||||
hostname resolves to multiple IPs, all of the IPs are included.
|
the hostname resolves to multiple IPs, all of the IPs are
|
||||||
If a width is provided with a hostname that the width is applied
|
included. If a width is provided with a hostname, the width is
|
||||||
to all of the hostnames IPs (if they are all either IPv4 or IPv6).
|
applied to all of the hostnames IPs (if they are all either IPv4
|
||||||
Widths cannot be supplied to hostnames that resolve to both IPv4
|
or IPv6). Widths cannot be supplied to hostnames that resolve to
|
||||||
and IPv6. Valid examples are example.com, example.com:8000,
|
both IPv4 and IPv6. Valid examples are example.com,
|
||||||
example.com/24, example.com/24:8000 and example.com:8000-9000.
|
example.com:8000, example.com/24, example.com/24:8000 and
|
||||||
|
example.com:8000-9000.
|
||||||
|
|
||||||
.. option:: --method <auto|nat|nft|tproxy|pf|ipfw>
|
.. option:: --method <auto|nat|nft|tproxy|pf|ipfw>
|
||||||
|
|
||||||
@ -141,7 +142,10 @@ Options
|
|||||||
The remote hostname and optional username and ssh
|
The remote hostname and optional username and ssh
|
||||||
port number to use for connecting to the remote server.
|
port number to use for connecting to the remote server.
|
||||||
For example, example.com, testuser@example.com,
|
For example, example.com, testuser@example.com,
|
||||||
testuser@example.com:2222, or example.com:2244.
|
testuser@example.com:2222, or example.com:2244. This
|
||||||
|
hostname is passed to ssh, so it will recognize any
|
||||||
|
aliases and settings you may have configured in
|
||||||
|
~/.ssh/config.
|
||||||
|
|
||||||
.. option:: -x <subnet>, --exclude=<subnet>
|
.. option:: -x <subnet>, --exclude=<subnet>
|
||||||
|
|
||||||
@ -274,9 +278,10 @@ Options
|
|||||||
Set the file name for the sudoers.d file to be added. Default is
|
Set the file name for the sudoers.d file to be added. Default is
|
||||||
"sshuttle_auto". Only works with --sudoers.
|
"sshuttle_auto". Only works with --sudoers.
|
||||||
|
|
||||||
.. option:: -t, --tmark
|
.. option:: -t <mark>, --tmark=<mark>
|
||||||
|
|
||||||
Transproxy optional traffic mark with provided MARK value.
|
An option used by the tproxy method: Use the specified traffic
|
||||||
|
mark. The mark must be a hexadecimal value. Defaults to 0x01.
|
||||||
|
|
||||||
.. option:: --version
|
.. option:: --version
|
||||||
|
|
||||||
@ -305,11 +310,8 @@ Arguments read from a file must be one per line, as shown below::
|
|||||||
--option2
|
--option2
|
||||||
value2
|
value2
|
||||||
|
|
||||||
Comments in config file
|
The configuration file supports comments for human-readable
|
||||||
.......................
|
annotations. For example::
|
||||||
|
|
||||||
It's possible to add comments in the configuration file. This allows annotating the
|
|
||||||
various subnets with human-readable descriptions, like::
|
|
||||||
|
|
||||||
# company-internal API
|
# company-internal API
|
||||||
8.8.8.8/32
|
8.8.8.8/32
|
||||||
@ -319,51 +321,96 @@ various subnets with human-readable descriptions, like::
|
|||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
Test locally by proxying all local connections, without using ssh::
|
|
||||||
|
|
||||||
$ sshuttle -v 0/0
|
Use the following command to route all IPv4 TCP traffic through remote
|
||||||
|
(-r) host example.com (and possibly other traffic too, depending on
|
||||||
|
the selected --method). The 0/0 subnet, short for 0.0.0.0/0, matches
|
||||||
|
all IPv4 addresses. The ::/0 subnet, matching all IPv6 addresses could
|
||||||
|
be added to the example. We also exclude (-x) example.com:22 so that
|
||||||
|
we can establish ssh connections from our local machine to the remote
|
||||||
|
host without them being routed through sshuttle. Excluding the remote
|
||||||
|
host may be necessary on some machines for sshuttle to work properly.
|
||||||
|
Press Ctrl+C to exit. To also route DNS queries through sshuttle, try
|
||||||
|
adding --dns. Add or remove -v options to see more or less
|
||||||
|
information::
|
||||||
|
|
||||||
Starting sshuttle proxy.
|
$ sshuttle -r example.com -x example.com:22 0/0
|
||||||
Listening on ('0.0.0.0', 12300).
|
|
||||||
[local sudo] Password:
|
Starting sshuttle proxy (version ...).
|
||||||
firewall manager ready.
|
[local sudo] Password:
|
||||||
c : connecting to server...
|
fw: Starting firewall with Python version 3.9.5
|
||||||
s: available routes:
|
fw: ready method name nat.
|
||||||
s: 192.168.42.0/24
|
c : IPv6 disabled since it isn't supported by method nat.
|
||||||
c : connected.
|
c : Method: nat
|
||||||
firewall manager: starting transproxy.
|
c : IPv4: on
|
||||||
c : Accept: 192.168.42.106:50035 -> 192.168.42.121:139.
|
c : IPv6: off (not available with nat method)
|
||||||
c : Accept: 192.168.42.121:47523 -> 77.141.99.22:443.
|
c : UDP : off (not available with nat method)
|
||||||
...etc...
|
c : DNS : off (available)
|
||||||
|
c : User: off (available)
|
||||||
|
c : Subnets to forward through remote host (type, IP, cidr mask width, startPort, endPort):
|
||||||
|
c : (<AddressFamily.AF_INET: 2>, '0.0.0.0', 0, 0, 0)
|
||||||
|
c : Subnets to exclude from forwarding:
|
||||||
|
c : (<AddressFamily.AF_INET: 2>, '...', 32, 22, 22)
|
||||||
|
c : (<AddressFamily.AF_INET: 2>, '127.0.0.1', 32, 0, 0)
|
||||||
|
c : TCP redirector listening on ('127.0.0.1', 12299).
|
||||||
|
c : Starting client with Python version 3.9.5
|
||||||
|
c : Connecting to server...
|
||||||
|
user@example.com's password:
|
||||||
|
s: Starting server with Python version 3.6.8
|
||||||
|
s: latency control setting = True
|
||||||
|
s: auto-nets:False
|
||||||
|
c : Connected to server.
|
||||||
|
fw: setting up.
|
||||||
|
fw: iptables -w -t nat -N sshuttle-12299
|
||||||
|
fw: iptables -w -t nat -F sshuttle-12299
|
||||||
|
...
|
||||||
|
Accept: 192.168.42.121:60554 -> 77.141.99.22:22.
|
||||||
^C
|
^C
|
||||||
firewall manager: undoing changes.
|
|
||||||
KeyboardInterrupt
|
|
||||||
c : Keyboard interrupt: exiting.
|
c : Keyboard interrupt: exiting.
|
||||||
c : SW#8:192.168.42.121:47523: deleting
|
c : SW'unknown':Mux#1: deleting (1 remain)
|
||||||
c : SW#6:192.168.42.106:50035: deleting
|
c : SW#7:192.168.42.121:60554: deleting (0 remain)
|
||||||
|
|
||||||
Test connection to a remote server, with automatic hostname
|
|
||||||
|
Connect to a remote server, with automatic hostname
|
||||||
and subnet guessing::
|
and subnet guessing::
|
||||||
|
|
||||||
$ sshuttle -vNHr example.org
|
$ sshuttle -vNHr example.com -x example.com:22
|
||||||
|
Starting sshuttle proxy (version ...).
|
||||||
Starting sshuttle proxy.
|
[local sudo] Password:
|
||||||
Listening on ('0.0.0.0', 12300).
|
fw: Starting firewall with Python version 3.9.5
|
||||||
firewall manager ready.
|
fw: ready method name nat.
|
||||||
c : connecting to server...
|
c : IPv6 disabled since it isn't supported by method nat.
|
||||||
|
c : Method: nat
|
||||||
|
c : IPv4: on
|
||||||
|
c : IPv6: off (not available with nat method)
|
||||||
|
c : UDP : off (not available with nat method)
|
||||||
|
c : DNS : off (available)
|
||||||
|
c : User: off (available)
|
||||||
|
c : Subnets to forward through remote host (type, IP, cidr mask width, startPort, endPort):
|
||||||
|
c : NOTE: Additional subnets to forward may be added below by --auto-nets.
|
||||||
|
c : Subnets to exclude from forwarding:
|
||||||
|
c : (<AddressFamily.AF_INET: 2>, '...', 32, 22, 22)
|
||||||
|
c : (<AddressFamily.AF_INET: 2>, '127.0.0.1', 32, 0, 0)
|
||||||
|
c : TCP redirector listening on ('127.0.0.1', 12300).
|
||||||
|
c : Starting client with Python version 3.9.5
|
||||||
|
c : Connecting to server...
|
||||||
|
user@example.com's password:
|
||||||
|
s: Starting server with Python version 3.6.8
|
||||||
|
s: latency control setting = True
|
||||||
|
s: auto-nets:True
|
||||||
|
c : Connected to server.
|
||||||
|
c : seed_hosts: []
|
||||||
s: available routes:
|
s: available routes:
|
||||||
s: 77.141.99.0/24
|
s: 77.141.99.0/24
|
||||||
c : connected.
|
fw: setting up.
|
||||||
c : seed_hosts: []
|
fw: iptables -w -t nat -N sshuttle-12300
|
||||||
firewall manager: starting transproxy.
|
fw: iptables -w -t nat -F sshuttle-12300
|
||||||
hostwatch: Found: testbox1: 1.2.3.4
|
...
|
||||||
hostwatch: Found: mytest2: 5.6.7.8
|
|
||||||
hostwatch: Found: domaincontroller: 99.1.2.3
|
|
||||||
c : Accept: 192.168.42.121:60554 -> 77.141.99.22:22.
|
c : Accept: 192.168.42.121:60554 -> 77.141.99.22:22.
|
||||||
^C
|
^C
|
||||||
firewall manager: undoing changes.
|
|
||||||
c : Keyboard interrupt: exiting.
|
c : Keyboard interrupt: exiting.
|
||||||
c : SW#6:192.168.42.121:60554: deleting
|
c : SW'unknown':Mux#1: deleting (1 remain)
|
||||||
|
c : SW#7:192.168.42.121:60554: deleting (0 remain)
|
||||||
|
|
||||||
Run :program:`sshuttle` with a `/etc/sshuttle.conf` configuration file::
|
Run :program:`sshuttle` with a `/etc/sshuttle.conf` configuration file::
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@ There are some things you need to consider for TPROXY to work:
|
|||||||
ip -6 route add local default dev lo table 100
|
ip -6 route add local default dev lo table 100
|
||||||
ip -6 rule add fwmark {TMARK} lookup 100
|
ip -6 rule add fwmark {TMARK} lookup 100
|
||||||
|
|
||||||
where {TMARK} is the identifier mark passed with -t or --tmark flag (default value is 1).
|
where {TMARK} is the identifier mark passed with -t or --tmark flag
|
||||||
|
as a hexadecimal string (default value is '0x01').
|
||||||
|
|
||||||
- The ``--auto-nets`` feature does not detect IPv6 routes automatically. Add IPv6
|
- The ``--auto-nets`` feature does not detect IPv6 routes automatically. Add IPv6
|
||||||
routes manually. e.g. by adding ``'::/0'`` to the end of the command line.
|
routes manually. e.g. by adding ``'::/0'`` to the end of the command line.
|
||||||
|
@ -11,6 +11,10 @@ Forward all traffic::
|
|||||||
sshuttle -r username@sshserver 0.0.0.0/0
|
sshuttle -r username@sshserver 0.0.0.0/0
|
||||||
|
|
||||||
- Use the :option:`sshuttle -r` parameter to specify a remote server.
|
- Use the :option:`sshuttle -r` parameter to specify a remote server.
|
||||||
|
One some systems, you may also need to use the :option:`sshuttle -x`
|
||||||
|
parameter to exclude sshserver or sshserver:22 so that your local
|
||||||
|
machine can communicate directly to sshserver without it being
|
||||||
|
redirected by sshuttle.
|
||||||
|
|
||||||
- By default sshuttle will automatically choose a method to use. Override with
|
- By default sshuttle will automatically choose a method to use. Override with
|
||||||
the :option:`sshuttle --method` parameter.
|
the :option:`sshuttle --method` parameter.
|
||||||
|
@ -201,12 +201,11 @@ class FirewallClient:
|
|||||||
|
|
||||||
def __init__(self, method_name, sudo_pythonpath, ttl):
|
def __init__(self, method_name, sudo_pythonpath, ttl):
|
||||||
self.auto_nets = []
|
self.auto_nets = []
|
||||||
python_path = os.path.dirname(os.path.dirname(__file__))
|
|
||||||
argvbase = ([sys.executable, sys.argv[0]] +
|
argvbase = ([sys.executable, sys.argv[0]] +
|
||||||
['-v'] * (helpers.verbose or 0) +
|
['-v'] * (helpers.verbose or 0) +
|
||||||
['--method', method_name] +
|
['--method', method_name] +
|
||||||
['--firewall'] +
|
['--firewall'])
|
||||||
['--ttl', str(ttl)])
|
|
||||||
if ssyslog._p:
|
if ssyslog._p:
|
||||||
argvbase += ['--syslog']
|
argvbase += ['--syslog']
|
||||||
|
|
||||||
@ -224,7 +223,8 @@ class FirewallClient:
|
|||||||
|
|
||||||
if sudo_pythonpath:
|
if sudo_pythonpath:
|
||||||
elev_prefix += ['/usr/bin/env',
|
elev_prefix += ['/usr/bin/env',
|
||||||
'PYTHONPATH=%s' % python_path]
|
'PYTHONPATH=%s' %
|
||||||
|
os.path.dirname(os.path.dirname(__file__))]
|
||||||
argv_tries = [elev_prefix + argvbase, argvbase]
|
argv_tries = [elev_prefix + argvbase, argvbase]
|
||||||
|
|
||||||
# we can't use stdin/stdout=subprocess.PIPE here, as we normally would,
|
# we can't use stdin/stdout=subprocess.PIPE here, as we normally would,
|
||||||
@ -261,7 +261,7 @@ class FirewallClient:
|
|||||||
|
|
||||||
def setup(self, subnets_include, subnets_exclude, nslist,
|
def setup(self, subnets_include, subnets_exclude, nslist,
|
||||||
redirectport_v6, redirectport_v4, dnsport_v6, dnsport_v4, udp,
|
redirectport_v6, redirectport_v4, dnsport_v6, dnsport_v4, udp,
|
||||||
user, tmark, ttl):
|
user, ttl, tmark):
|
||||||
self.subnets_include = subnets_include
|
self.subnets_include = subnets_include
|
||||||
self.subnets_exclude = subnets_exclude
|
self.subnets_exclude = subnets_exclude
|
||||||
self.nslist = nslist
|
self.nslist = nslist
|
||||||
@ -311,7 +311,9 @@ class FirewallClient:
|
|||||||
else:
|
else:
|
||||||
user = b'%d' % self.user
|
user = b'%d' % self.user
|
||||||
|
|
||||||
self.pfile.write(b'GO %d %s\n' % (udp, user))
|
self.pfile.write(b'GO %d %s %d %s\n' %
|
||||||
|
(udp, user, self.ttl,
|
||||||
|
bytes(self.tmark, 'ascii')))
|
||||||
self.pfile.flush()
|
self.pfile.flush()
|
||||||
|
|
||||||
line = self.pfile.readline()
|
line = self.pfile.readline()
|
||||||
@ -1003,7 +1005,7 @@ def main(listenip_v6, listenip_v4,
|
|||||||
# start the firewall
|
# start the firewall
|
||||||
fw.setup(subnets_include, subnets_exclude, nslist,
|
fw.setup(subnets_include, subnets_exclude, nslist,
|
||||||
redirectport_v6, redirectport_v4, dnsport_v6, dnsport_v4,
|
redirectport_v6, redirectport_v4, dnsport_v6, dnsport_v4,
|
||||||
required.udp, user, tmark, ttl)
|
required.udp, user, ttl, tmark)
|
||||||
|
|
||||||
# start the client process
|
# start the client process
|
||||||
try:
|
try:
|
||||||
|
@ -20,7 +20,7 @@ def main():
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
if not opt.sudoers_filename:
|
if not opt.sudoers_filename:
|
||||||
log('--sudoers-file must be set or omited.')
|
log('--sudoers-file must be set or omitted.')
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
sudoers(
|
sudoers(
|
||||||
@ -85,6 +85,13 @@ def main():
|
|||||||
ipport_v4 = "auto"
|
ipport_v4 = "auto"
|
||||||
# parse_ipport6('[::1]:0')
|
# parse_ipport6('[::1]:0')
|
||||||
ipport_v6 = "auto" if not opt.disable_ipv6 else None
|
ipport_v6 = "auto" if not opt.disable_ipv6 else None
|
||||||
|
try:
|
||||||
|
int(opt.tmark, 16)
|
||||||
|
except ValueError:
|
||||||
|
parser.error("--tmark must be a hexadecimal value")
|
||||||
|
opt.tmark = opt.tmark.lower() # make 'x' in 0x lowercase
|
||||||
|
if not opt.tmark.startswith("0x"): # accept without 0x prefix
|
||||||
|
opt.tmark = "0x%s" % opt.tmark
|
||||||
if opt.syslog:
|
if opt.syslog:
|
||||||
ssyslog.start_syslog()
|
ssyslog.start_syslog()
|
||||||
ssyslog.close_stdin()
|
ssyslog.close_stdin()
|
||||||
|
@ -223,11 +223,13 @@ def main(method_name, syslog, ttl):
|
|||||||
raise Fatal('expected GO but got %r' % line)
|
raise Fatal('expected GO but got %r' % line)
|
||||||
|
|
||||||
_, _, args = line.partition(" ")
|
_, _, args = line.partition(" ")
|
||||||
udp, user = args.strip().split(" ", 1)
|
udp, user, ttl, tmark = args.strip().split(" ", 3)
|
||||||
udp = bool(int(udp))
|
udp = bool(int(udp))
|
||||||
if user == '-':
|
if user == '-':
|
||||||
user = None
|
user = None
|
||||||
debug2('Got udp: %r, user: %r' % (udp, user))
|
ttl = int(ttl)
|
||||||
|
debug2('Got udp: %r, user: %r, ttl: %s, tmark: %s' %
|
||||||
|
(udp, user, ttl, tmark))
|
||||||
|
|
||||||
subnets_v6 = [i for i in subnets if i[0] == socket.AF_INET6]
|
subnets_v6 = [i for i in subnets if i[0] == socket.AF_INET6]
|
||||||
nslist_v6 = [i for i in nslist if i[0] == socket.AF_INET6]
|
nslist_v6 = [i for i in nslist if i[0] == socket.AF_INET6]
|
||||||
@ -242,14 +244,14 @@ def main(method_name, syslog, ttl):
|
|||||||
method.setup_firewall(
|
method.setup_firewall(
|
||||||
port_v6, dnsport_v6, nslist_v6,
|
port_v6, dnsport_v6, nslist_v6,
|
||||||
socket.AF_INET6, subnets_v6, udp,
|
socket.AF_INET6, subnets_v6, udp,
|
||||||
user, ttl)
|
user, ttl, tmark)
|
||||||
|
|
||||||
if subnets_v4 or nslist_v4:
|
if subnets_v4 or nslist_v4:
|
||||||
debug2('setting up IPv4.')
|
debug2('setting up IPv4.')
|
||||||
method.setup_firewall(
|
method.setup_firewall(
|
||||||
port_v4, dnsport_v4, nslist_v4,
|
port_v4, dnsport_v4, nslist_v4,
|
||||||
socket.AF_INET, subnets_v4, udp,
|
socket.AF_INET, subnets_v4, udp,
|
||||||
user, ttl)
|
user, ttl, tmark)
|
||||||
|
|
||||||
flush_systemd_dns_cache()
|
flush_systemd_dns_cache()
|
||||||
stdout.write('STARTED\n')
|
stdout.write('STARTED\n')
|
||||||
|
@ -16,8 +16,6 @@ NETSTAT_POLL_TIME = 30
|
|||||||
CACHEFILE = os.path.expanduser('~/.sshuttle.hosts')
|
CACHEFILE = os.path.expanduser('~/.sshuttle.hosts')
|
||||||
|
|
||||||
|
|
||||||
_nmb_ok = True
|
|
||||||
_smb_ok = True
|
|
||||||
hostnames = {}
|
hostnames = {}
|
||||||
queue = {}
|
queue = {}
|
||||||
try:
|
try:
|
||||||
@ -141,110 +139,11 @@ def _check_netstat():
|
|||||||
check_host(ip)
|
check_host(ip)
|
||||||
|
|
||||||
|
|
||||||
def _check_smb(hostname):
|
|
||||||
return
|
|
||||||
global _smb_ok
|
|
||||||
if not _smb_ok:
|
|
||||||
return
|
|
||||||
debug2(' > smb: %s' % hostname)
|
|
||||||
argv = ['smbclient', '-U', '%', '-L', hostname]
|
|
||||||
try:
|
|
||||||
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null,
|
|
||||||
env=get_env())
|
|
||||||
lines = p.stdout.readlines()
|
|
||||||
p.wait()
|
|
||||||
except OSError:
|
|
||||||
_, e = sys.exc_info()[:2]
|
|
||||||
log('%r failed: %r' % (argv, e))
|
|
||||||
_smb_ok = False
|
|
||||||
return
|
|
||||||
|
|
||||||
lines.reverse()
|
|
||||||
|
|
||||||
# junk at top
|
|
||||||
while lines:
|
|
||||||
line = lines.pop().strip()
|
|
||||||
if re.match(r'Server\s+', line):
|
|
||||||
break
|
|
||||||
|
|
||||||
# server list section:
|
|
||||||
# Server Comment
|
|
||||||
# ------ -------
|
|
||||||
while lines:
|
|
||||||
line = lines.pop().strip()
|
|
||||||
if not line or re.match(r'-+\s+-+', line):
|
|
||||||
continue
|
|
||||||
if re.match(r'Workgroup\s+Master', line):
|
|
||||||
break
|
|
||||||
words = line.split()
|
|
||||||
hostname = words[0].lower()
|
|
||||||
debug3('< %s' % hostname)
|
|
||||||
check_host(hostname)
|
|
||||||
|
|
||||||
# workgroup list section:
|
|
||||||
# Workgroup Master
|
|
||||||
# --------- ------
|
|
||||||
while lines:
|
|
||||||
line = lines.pop().strip()
|
|
||||||
if re.match(r'-+\s+', line):
|
|
||||||
continue
|
|
||||||
if not line:
|
|
||||||
break
|
|
||||||
words = line.split()
|
|
||||||
(workgroup, hostname) = (words[0].lower(), words[1].lower())
|
|
||||||
debug3('< group(%s) -> %s' % (workgroup, hostname))
|
|
||||||
check_host(hostname)
|
|
||||||
check_workgroup(workgroup)
|
|
||||||
|
|
||||||
if lines:
|
|
||||||
assert(0)
|
|
||||||
|
|
||||||
|
|
||||||
def _check_nmb(hostname, is_workgroup, is_master):
|
|
||||||
return
|
|
||||||
global _nmb_ok
|
|
||||||
if not _nmb_ok:
|
|
||||||
return
|
|
||||||
debug2(' > n%d%d: %s' % (is_workgroup, is_master, hostname))
|
|
||||||
argv = ['nmblookup'] + ['-M'] * is_master + ['--', hostname]
|
|
||||||
try:
|
|
||||||
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null,
|
|
||||||
env=get_env)
|
|
||||||
lines = p.stdout.readlines()
|
|
||||||
rv = p.wait()
|
|
||||||
except OSError:
|
|
||||||
_, e = sys.exc_info()[:2]
|
|
||||||
log('%r failed: %r' % (argv, e))
|
|
||||||
_nmb_ok = False
|
|
||||||
return
|
|
||||||
if rv:
|
|
||||||
log('%r returned %d' % (argv, rv))
|
|
||||||
return
|
|
||||||
for line in lines:
|
|
||||||
m = re.match(r'(\d+\.\d+\.\d+\.\d+) (\w+)<\w\w>\n', line)
|
|
||||||
if m:
|
|
||||||
g = m.groups()
|
|
||||||
(ip, name) = (g[0], g[1].lower())
|
|
||||||
debug3('< %s -> %s' % (name, ip))
|
|
||||||
if is_workgroup:
|
|
||||||
_enqueue(_check_smb, ip)
|
|
||||||
else:
|
|
||||||
found_host(name, ip)
|
|
||||||
check_host(name)
|
|
||||||
|
|
||||||
|
|
||||||
def check_host(hostname):
|
def check_host(hostname):
|
||||||
if _is_ip(hostname):
|
if _is_ip(hostname):
|
||||||
_enqueue(_check_revdns, hostname)
|
_enqueue(_check_revdns, hostname)
|
||||||
else:
|
else:
|
||||||
_enqueue(_check_dns, hostname)
|
_enqueue(_check_dns, hostname)
|
||||||
_enqueue(_check_smb, hostname)
|
|
||||||
_enqueue(_check_nmb, hostname, False, False)
|
|
||||||
|
|
||||||
|
|
||||||
def check_workgroup(hostname):
|
|
||||||
_enqueue(_check_nmb, hostname, True, False)
|
|
||||||
_enqueue(_check_nmb, hostname, True, True)
|
|
||||||
|
|
||||||
|
|
||||||
def _enqueue(op, *args):
|
def _enqueue(op, *args):
|
||||||
@ -277,8 +176,6 @@ def hw_main(seed_hosts, auto_hosts):
|
|||||||
_enqueue(_check_netstat)
|
_enqueue(_check_netstat)
|
||||||
check_host('localhost')
|
check_host('localhost')
|
||||||
check_host(socket.gethostname())
|
check_host(socket.gethostname())
|
||||||
check_workgroup('workgroup')
|
|
||||||
check_workgroup('-')
|
|
||||||
|
|
||||||
while 1:
|
while 1:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
|
@ -91,7 +91,7 @@ class BaseMethod(object):
|
|||||||
(key, self.name))
|
(key, self.name))
|
||||||
|
|
||||||
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
||||||
user):
|
user, ttl, tmark):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def restore_firewall(self, port, family, udp, user):
|
def restore_firewall(self, port, family, udp, user):
|
||||||
|
@ -189,7 +189,7 @@ class Method(BaseMethod):
|
|||||||
# udp_listener.v6.setsockopt(SOL_IPV6, IPV6_RECVDSTADDR, 1)
|
# udp_listener.v6.setsockopt(SOL_IPV6, IPV6_RECVDSTADDR, 1)
|
||||||
|
|
||||||
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
||||||
user, ttl):
|
user, ttl, tmark):
|
||||||
# IPv6 not supported
|
# IPv6 not supported
|
||||||
if family not in [socket.AF_INET]:
|
if family not in [socket.AF_INET]:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
|
@ -13,7 +13,7 @@ class Method(BaseMethod):
|
|||||||
# recently-started one will win (because we use "-I OUTPUT 1" instead of
|
# recently-started one will win (because we use "-I OUTPUT 1" instead of
|
||||||
# "-A OUTPUT").
|
# "-A OUTPUT").
|
||||||
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
||||||
user, ttl):
|
user, ttl, tmark):
|
||||||
if family != socket.AF_INET and family != socket.AF_INET6:
|
if family != socket.AF_INET and family != socket.AF_INET6:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'Address family "%s" unsupported by nat method_name'
|
'Address family "%s" unsupported by nat method_name'
|
||||||
|
@ -13,7 +13,7 @@ class Method(BaseMethod):
|
|||||||
# recently-started one will win (because we use "-I OUTPUT 1" instead of
|
# recently-started one will win (because we use "-I OUTPUT 1" instead of
|
||||||
# "-A OUTPUT").
|
# "-A OUTPUT").
|
||||||
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
||||||
user, ttl):
|
user, ttl, tmark):
|
||||||
if udp:
|
if udp:
|
||||||
raise Exception("UDP not supported by nft")
|
raise Exception("UDP not supported by nft")
|
||||||
|
|
||||||
|
@ -444,7 +444,7 @@ class Method(BaseMethod):
|
|||||||
return sock.getsockname()
|
return sock.getsockname()
|
||||||
|
|
||||||
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
||||||
user, ttl):
|
user, ttl, tmark):
|
||||||
if family not in [socket.AF_INET, socket.AF_INET6]:
|
if family not in [socket.AF_INET, socket.AF_INET6]:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'Address family "%s" unsupported by pf method_name'
|
'Address family "%s" unsupported by pf method_name'
|
||||||
|
@ -151,17 +151,7 @@ class Method(BaseMethod):
|
|||||||
udp_listener.v6.setsockopt(SOL_IPV6, IPV6_RECVORIGDSTADDR, 1)
|
udp_listener.v6.setsockopt(SOL_IPV6, IPV6_RECVORIGDSTADDR, 1)
|
||||||
|
|
||||||
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
||||||
user, ttl):
|
user, ttl, tmark):
|
||||||
if self.firewall is None:
|
|
||||||
tmark = '1'
|
|
||||||
else:
|
|
||||||
tmark = self.firewall.tmark
|
|
||||||
|
|
||||||
self.setup_firewall_tproxy(port, dnsport, nslist, family, subnets, udp,
|
|
||||||
user, tmark)
|
|
||||||
|
|
||||||
def setup_firewall_tproxy(self, port, dnsport, nslist, family, subnets,
|
|
||||||
udp, user, tmark):
|
|
||||||
if family not in [socket.AF_INET, socket.AF_INET6]:
|
if family not in [socket.AF_INET, socket.AF_INET6]:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'Address family "%s" unsupported by tproxy method'
|
'Address family "%s" unsupported by tproxy method'
|
||||||
@ -192,8 +182,8 @@ class Method(BaseMethod):
|
|||||||
_ipt('-F', divert_chain)
|
_ipt('-F', divert_chain)
|
||||||
_ipt('-N', tproxy_chain)
|
_ipt('-N', tproxy_chain)
|
||||||
_ipt('-F', tproxy_chain)
|
_ipt('-F', tproxy_chain)
|
||||||
_ipt('-I', 'OUTPUT', tmark, '-j', mark_chain)
|
_ipt('-I', 'OUTPUT', '1', '-j', mark_chain)
|
||||||
_ipt('-I', 'PREROUTING', tmark, '-j', tproxy_chain)
|
_ipt('-I', 'PREROUTING', '1', '-j', tproxy_chain)
|
||||||
|
|
||||||
# Don't have packets sent to any of our local IP addresses go
|
# Don't have packets sent to any of our local IP addresses go
|
||||||
# through the tproxy or mark chains.
|
# through the tproxy or mark chains.
|
||||||
@ -224,7 +214,7 @@ class Method(BaseMethod):
|
|||||||
'--dest', '%s/32' % ip,
|
'--dest', '%s/32' % ip,
|
||||||
'-m', 'udp', '-p', 'udp', '--dport', '53')
|
'-m', 'udp', '-p', 'udp', '--dport', '53')
|
||||||
_ipt('-A', tproxy_chain, '-j', 'TPROXY',
|
_ipt('-A', tproxy_chain, '-j', 'TPROXY',
|
||||||
'--tproxy-mark', '0x'+tmark+'/0x'+tmark,
|
'--tproxy-mark', tmark,
|
||||||
'--dest', '%s/32' % ip,
|
'--dest', '%s/32' % ip,
|
||||||
'-m', 'udp', '-p', 'udp', '--dport', '53',
|
'-m', 'udp', '-p', 'udp', '--dport', '53',
|
||||||
'--on-port', str(dnsport))
|
'--on-port', str(dnsport))
|
||||||
@ -249,7 +239,7 @@ class Method(BaseMethod):
|
|||||||
'-m', 'tcp',
|
'-m', 'tcp',
|
||||||
*tcp_ports)
|
*tcp_ports)
|
||||||
_ipt('-A', tproxy_chain, '-j', 'TPROXY',
|
_ipt('-A', tproxy_chain, '-j', 'TPROXY',
|
||||||
'--tproxy-mark', '0x'+tmark+'/0x'+tmark,
|
'--tproxy-mark', tmark,
|
||||||
'--dest', '%s/%s' % (snet, swidth),
|
'--dest', '%s/%s' % (snet, swidth),
|
||||||
'-m', 'tcp',
|
'-m', 'tcp',
|
||||||
*(tcp_ports + ('--on-port', str(port))))
|
*(tcp_ports + ('--on-port', str(port))))
|
||||||
@ -273,7 +263,7 @@ class Method(BaseMethod):
|
|||||||
'-m', 'udp',
|
'-m', 'udp',
|
||||||
*udp_ports)
|
*udp_ports)
|
||||||
_ipt('-A', tproxy_chain, '-j', 'TPROXY',
|
_ipt('-A', tproxy_chain, '-j', 'TPROXY',
|
||||||
'--tproxy-mark', '0x'+tmark+'/0x'+tmark,
|
'--tproxy-mark', tmark,
|
||||||
'--dest', '%s/%s' % (snet, swidth),
|
'--dest', '%s/%s' % (snet, swidth),
|
||||||
'-m', 'udp',
|
'-m', 'udp',
|
||||||
*(udp_ports + ('--on-port', str(port))))
|
*(udp_ports + ('--on-port', str(port))))
|
||||||
|
@ -132,6 +132,7 @@ def parse_ipport(s):
|
|||||||
|
|
||||||
|
|
||||||
def parse_list(lst):
|
def parse_list(lst):
|
||||||
|
"""Parse a comma separated string into a list."""
|
||||||
return re.split(r'[\s,]+', lst.strip()) if lst else []
|
return re.split(r'[\s,]+', lst.strip()) if lst else []
|
||||||
|
|
||||||
|
|
||||||
@ -220,6 +221,7 @@ parser.add_argument(
|
|||||||
type=parse_list,
|
type=parse_list,
|
||||||
help="""
|
help="""
|
||||||
capture and forward DNS requests made to the following servers
|
capture and forward DNS requests made to the following servers
|
||||||
|
(comma separated)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
@ -280,7 +282,7 @@ parser.add_argument(
|
|||||||
action="count",
|
action="count",
|
||||||
default=0,
|
default=0,
|
||||||
help="""
|
help="""
|
||||||
increase debug message verbosity
|
increase debug message verbosity (can be used more than once)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
@ -445,8 +447,9 @@ parser.add_argument(
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-t", "--tmark",
|
"-t", "--tmark",
|
||||||
metavar="[MARK]",
|
metavar="[MARK]",
|
||||||
default="1",
|
default="0x01",
|
||||||
help="""
|
help="""
|
||||||
transproxy optional traffic mark with provided MARK value
|
tproxy optional traffic mark with provided MARK value in
|
||||||
|
hexadecimal (default '0x01')
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
@ -15,7 +15,7 @@ NSLIST
|
|||||||
{inet},1.2.3.33
|
{inet},1.2.3.33
|
||||||
{inet6},2404:6800:4004:80c::33
|
{inet6},2404:6800:4004:80c::33
|
||||||
PORTS 1024,1025,1026,1027
|
PORTS 1024,1025,1026,1027
|
||||||
GO 1 -
|
GO 1 - 63 0x01
|
||||||
HOST 1.2.3.3,existing
|
HOST 1.2.3.3,existing
|
||||||
""".format(inet=AF_INET, inet6=AF_INET6))
|
""".format(inet=AF_INET, inet6=AF_INET6))
|
||||||
stdout = Mock()
|
stdout = Mock()
|
||||||
@ -126,7 +126,7 @@ def test_main(mock_get_method, mock_setup_daemon, mock_rewrite_etc_hosts):
|
|||||||
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 80, 80)],
|
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 80, 80)],
|
||||||
True,
|
True,
|
||||||
None,
|
None,
|
||||||
63),
|
63, '0x01'),
|
||||||
call().setup_firewall(
|
call().setup_firewall(
|
||||||
1025, 1027,
|
1025, 1027,
|
||||||
[(AF_INET, u'1.2.3.33')],
|
[(AF_INET, u'1.2.3.33')],
|
||||||
@ -135,7 +135,7 @@ def test_main(mock_get_method, mock_setup_daemon, mock_rewrite_etc_hosts):
|
|||||||
(AF_INET, 32, True, u'1.2.3.66', 8080, 8080)],
|
(AF_INET, 32, True, u'1.2.3.66', 8080, 8080)],
|
||||||
True,
|
True,
|
||||||
None,
|
None,
|
||||||
63),
|
63, '0x01'),
|
||||||
call().restore_firewall(1024, AF_INET6, True, None),
|
call().restore_firewall(1024, AF_INET6, True, None),
|
||||||
call().restore_firewall(1025, AF_INET, True, None),
|
call().restore_firewall(1025, AF_INET, True, None),
|
||||||
]
|
]
|
||||||
|
@ -103,7 +103,7 @@ def test_setup_firewall(mock_ipt_chain_exists, mock_ipt_ttl, mock_ipt):
|
|||||||
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 80, 80)],
|
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 80, 80)],
|
||||||
False,
|
False,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
|
|
||||||
assert mock_ipt_chain_exists.mock_calls == [
|
assert mock_ipt_chain_exists.mock_calls == [
|
||||||
call(AF_INET6, 'nat', 'sshuttle-1024')
|
call(AF_INET6, 'nat', 'sshuttle-1024')
|
||||||
@ -150,7 +150,7 @@ def test_setup_firewall(mock_ipt_chain_exists, mock_ipt_ttl, mock_ipt):
|
|||||||
(AF_INET, 32, True, u'1.2.3.66', 8080, 8080)],
|
(AF_INET, 32, True, u'1.2.3.66', 8080, 8080)],
|
||||||
True,
|
True,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
assert str(excinfo.value) == 'UDP not supported by nat method_name'
|
assert str(excinfo.value) == 'UDP not supported by nat method_name'
|
||||||
assert mock_ipt_chain_exists.mock_calls == []
|
assert mock_ipt_chain_exists.mock_calls == []
|
||||||
assert mock_ipt_ttl.mock_calls == []
|
assert mock_ipt_ttl.mock_calls == []
|
||||||
@ -164,7 +164,7 @@ def test_setup_firewall(mock_ipt_chain_exists, mock_ipt_ttl, mock_ipt):
|
|||||||
(AF_INET, 32, True, u'1.2.3.66', 8080, 8080)],
|
(AF_INET, 32, True, u'1.2.3.66', 8080, 8080)],
|
||||||
False,
|
False,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
assert mock_ipt_chain_exists.mock_calls == [
|
assert mock_ipt_chain_exists.mock_calls == [
|
||||||
call(AF_INET, 'nat', 'sshuttle-1025')
|
call(AF_INET, 'nat', 'sshuttle-1025')
|
||||||
]
|
]
|
||||||
|
@ -187,7 +187,7 @@ def test_setup_firewall_darwin(mock_pf_get_dev, mock_ioctl, mock_pfctl):
|
|||||||
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 8080, 8080)],
|
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 8080, 8080)],
|
||||||
False,
|
False,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
assert mock_ioctl.mock_calls == [
|
assert mock_ioctl.mock_calls == [
|
||||||
call(mock_pf_get_dev(), 0xC4704433, ANY),
|
call(mock_pf_get_dev(), 0xC4704433, ANY),
|
||||||
call(mock_pf_get_dev(), 0xCC20441A, ANY),
|
call(mock_pf_get_dev(), 0xCC20441A, ANY),
|
||||||
@ -227,7 +227,7 @@ def test_setup_firewall_darwin(mock_pf_get_dev, mock_ioctl, mock_pfctl):
|
|||||||
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
||||||
True,
|
True,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
assert str(excinfo.value) == 'UDP not supported by pf method_name'
|
assert str(excinfo.value) == 'UDP not supported by pf method_name'
|
||||||
assert mock_pf_get_dev.mock_calls == []
|
assert mock_pf_get_dev.mock_calls == []
|
||||||
assert mock_ioctl.mock_calls == []
|
assert mock_ioctl.mock_calls == []
|
||||||
@ -241,7 +241,7 @@ def test_setup_firewall_darwin(mock_pf_get_dev, mock_ioctl, mock_pfctl):
|
|||||||
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
||||||
False,
|
False,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
assert mock_ioctl.mock_calls == [
|
assert mock_ioctl.mock_calls == [
|
||||||
call(mock_pf_get_dev(), 0xC4704433, ANY),
|
call(mock_pf_get_dev(), 0xC4704433, ANY),
|
||||||
call(mock_pf_get_dev(), 0xCC20441A, ANY),
|
call(mock_pf_get_dev(), 0xCC20441A, ANY),
|
||||||
@ -302,7 +302,7 @@ def test_setup_firewall_freebsd(mock_pf_get_dev, mock_ioctl, mock_pfctl,
|
|||||||
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 8080, 8080)],
|
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 8080, 8080)],
|
||||||
False,
|
False,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
|
|
||||||
assert mock_pfctl.mock_calls == [
|
assert mock_pfctl.mock_calls == [
|
||||||
call('-s all'),
|
call('-s all'),
|
||||||
@ -335,7 +335,7 @@ def test_setup_firewall_freebsd(mock_pf_get_dev, mock_ioctl, mock_pfctl,
|
|||||||
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
||||||
True,
|
True,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
assert str(excinfo.value) == 'UDP not supported by pf method_name'
|
assert str(excinfo.value) == 'UDP not supported by pf method_name'
|
||||||
assert mock_pf_get_dev.mock_calls == []
|
assert mock_pf_get_dev.mock_calls == []
|
||||||
assert mock_ioctl.mock_calls == []
|
assert mock_ioctl.mock_calls == []
|
||||||
@ -349,7 +349,7 @@ def test_setup_firewall_freebsd(mock_pf_get_dev, mock_ioctl, mock_pfctl,
|
|||||||
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
||||||
False,
|
False,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
assert mock_ioctl.mock_calls == [
|
assert mock_ioctl.mock_calls == [
|
||||||
call(mock_pf_get_dev(), 0xC4704433, ANY),
|
call(mock_pf_get_dev(), 0xC4704433, ANY),
|
||||||
call(mock_pf_get_dev(), 0xCBE0441A, ANY),
|
call(mock_pf_get_dev(), 0xCBE0441A, ANY),
|
||||||
@ -408,7 +408,7 @@ def test_setup_firewall_openbsd(mock_pf_get_dev, mock_ioctl, mock_pfctl):
|
|||||||
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 8080, 8080)],
|
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 8080, 8080)],
|
||||||
False,
|
False,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
|
|
||||||
assert mock_ioctl.mock_calls == [
|
assert mock_ioctl.mock_calls == [
|
||||||
call(mock_pf_get_dev(), 0xcd60441a, ANY),
|
call(mock_pf_get_dev(), 0xcd60441a, ANY),
|
||||||
@ -445,7 +445,7 @@ def test_setup_firewall_openbsd(mock_pf_get_dev, mock_ioctl, mock_pfctl):
|
|||||||
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
||||||
True,
|
True,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
assert str(excinfo.value) == 'UDP not supported by pf method_name'
|
assert str(excinfo.value) == 'UDP not supported by pf method_name'
|
||||||
assert mock_pf_get_dev.mock_calls == []
|
assert mock_pf_get_dev.mock_calls == []
|
||||||
assert mock_ioctl.mock_calls == []
|
assert mock_ioctl.mock_calls == []
|
||||||
@ -459,7 +459,7 @@ def test_setup_firewall_openbsd(mock_pf_get_dev, mock_ioctl, mock_pfctl):
|
|||||||
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
||||||
False,
|
False,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
assert mock_ioctl.mock_calls == [
|
assert mock_ioctl.mock_calls == [
|
||||||
call(mock_pf_get_dev(), 0xcd60441a, ANY),
|
call(mock_pf_get_dev(), 0xcd60441a, ANY),
|
||||||
call(mock_pf_get_dev(), 0xcd60441a, ANY),
|
call(mock_pf_get_dev(), 0xcd60441a, ANY),
|
||||||
|
@ -109,7 +109,7 @@ def test_setup_firewall(mock_ipt_chain_exists, mock_ipt_ttl, mock_ipt):
|
|||||||
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 8080, 8080)],
|
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 8080, 8080)],
|
||||||
True,
|
True,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
assert mock_ipt_chain_exists.mock_calls == [
|
assert mock_ipt_chain_exists.mock_calls == [
|
||||||
call(AF_INET6, 'mangle', 'sshuttle-m-1024'),
|
call(AF_INET6, 'mangle', 'sshuttle-m-1024'),
|
||||||
call(AF_INET6, 'mangle', 'sshuttle-t-1024'),
|
call(AF_INET6, 'mangle', 'sshuttle-t-1024'),
|
||||||
@ -139,17 +139,17 @@ def test_setup_firewall(mock_ipt_chain_exists, mock_ipt_ttl, mock_ipt):
|
|||||||
call(AF_INET6, 'mangle', '-A', 'sshuttle-m-1024', '-j', 'RETURN',
|
call(AF_INET6, 'mangle', '-A', 'sshuttle-m-1024', '-j', 'RETURN',
|
||||||
'-m', 'addrtype', '--dst-type', 'LOCAL'),
|
'-m', 'addrtype', '--dst-type', 'LOCAL'),
|
||||||
call(AF_INET6, 'mangle', '-A', 'sshuttle-d-1024', '-j', 'MARK',
|
call(AF_INET6, 'mangle', '-A', 'sshuttle-d-1024', '-j', 'MARK',
|
||||||
'--set-mark', '1'),
|
'--set-mark', '0x01'),
|
||||||
call(AF_INET6, 'mangle', '-A', 'sshuttle-d-1024', '-j', 'ACCEPT'),
|
call(AF_INET6, 'mangle', '-A', 'sshuttle-d-1024', '-j', 'ACCEPT'),
|
||||||
call(AF_INET6, 'mangle', '-A', 'sshuttle-t-1024', '-m', 'socket',
|
call(AF_INET6, 'mangle', '-A', 'sshuttle-t-1024', '-m', 'socket',
|
||||||
'-j', 'sshuttle-d-1024', '-m', 'tcp', '-p', 'tcp'),
|
'-j', 'sshuttle-d-1024', '-m', 'tcp', '-p', 'tcp'),
|
||||||
call(AF_INET6, 'mangle', '-A', 'sshuttle-t-1024', '-m', 'socket',
|
call(AF_INET6, 'mangle', '-A', 'sshuttle-t-1024', '-m', 'socket',
|
||||||
'-j', 'sshuttle-d-1024', '-m', 'udp', '-p', 'udp'),
|
'-j', 'sshuttle-d-1024', '-m', 'udp', '-p', 'udp'),
|
||||||
call(AF_INET6, 'mangle', '-A', 'sshuttle-m-1024', '-j', 'MARK',
|
call(AF_INET6, 'mangle', '-A', 'sshuttle-m-1024', '-j', 'MARK',
|
||||||
'--set-mark', '1', '--dest', u'2404:6800:4004:80c::33/32',
|
'--set-mark', '0x01', '--dest', u'2404:6800:4004:80c::33/32',
|
||||||
'-m', 'udp', '-p', 'udp', '--dport', '53'),
|
'-m', 'udp', '-p', 'udp', '--dport', '53'),
|
||||||
call(AF_INET6, 'mangle', '-A', 'sshuttle-t-1024', '-j', 'TPROXY',
|
call(AF_INET6, 'mangle', '-A', 'sshuttle-t-1024', '-j', 'TPROXY',
|
||||||
'--tproxy-mark', '0x1/0x1',
|
'--tproxy-mark', '0x01',
|
||||||
'--dest', u'2404:6800:4004:80c::33/32',
|
'--dest', u'2404:6800:4004:80c::33/32',
|
||||||
'-m', 'udp', '-p', 'udp', '--dport', '53', '--on-port', '1026'),
|
'-m', 'udp', '-p', 'udp', '--dport', '53', '--on-port', '1026'),
|
||||||
call(AF_INET6, 'mangle', '-A', 'sshuttle-m-1024', '-j', 'RETURN',
|
call(AF_INET6, 'mangle', '-A', 'sshuttle-m-1024', '-j', 'RETURN',
|
||||||
@ -165,17 +165,19 @@ def test_setup_firewall(mock_ipt_chain_exists, mock_ipt_ttl, mock_ipt):
|
|||||||
'--dest', u'2404:6800:4004:80c::101f/128',
|
'--dest', u'2404:6800:4004:80c::101f/128',
|
||||||
'-m', 'udp', '-p', 'udp', '--dport', '8080:8080'),
|
'-m', 'udp', '-p', 'udp', '--dport', '8080:8080'),
|
||||||
call(AF_INET6, 'mangle', '-A', 'sshuttle-m-1024', '-j', 'MARK',
|
call(AF_INET6, 'mangle', '-A', 'sshuttle-m-1024', '-j', 'MARK',
|
||||||
'--set-mark', '1', '--dest', u'2404:6800:4004:80c::/64',
|
'--set-mark', '0x01', '--dest', u'2404:6800:4004:80c::/64',
|
||||||
'-m', 'tcp', '-p', 'tcp', '--dport', '8000:9000'),
|
'-m', 'tcp', '-p', 'tcp', '--dport', '8000:9000'),
|
||||||
call(AF_INET6, 'mangle', '-A', 'sshuttle-t-1024', '-j', 'TPROXY',
|
call(AF_INET6, 'mangle', '-A', 'sshuttle-t-1024', '-j', 'TPROXY',
|
||||||
'--tproxy-mark', '0x1/0x1', '--dest', u'2404:6800:4004:80c::/64',
|
'--tproxy-mark', '0x01', '--dest',
|
||||||
|
u'2404:6800:4004:80c::/64',
|
||||||
'-m', 'tcp', '-p', 'tcp', '--dport', '8000:9000',
|
'-m', 'tcp', '-p', 'tcp', '--dport', '8000:9000',
|
||||||
'--on-port', '1024'),
|
'--on-port', '1024'),
|
||||||
call(AF_INET6, 'mangle', '-A', 'sshuttle-m-1024', '-j', 'MARK',
|
call(AF_INET6, 'mangle', '-A', 'sshuttle-m-1024', '-j', 'MARK',
|
||||||
'--set-mark', '1', '--dest', u'2404:6800:4004:80c::/64',
|
'--set-mark', '0x01', '--dest', u'2404:6800:4004:80c::/64',
|
||||||
'-m', 'udp', '-p', 'udp', '--dport', '8000:9000'),
|
'-m', 'udp', '-p', 'udp', '--dport', '8000:9000'),
|
||||||
call(AF_INET6, 'mangle', '-A', 'sshuttle-t-1024', '-j', 'TPROXY',
|
call(AF_INET6, 'mangle', '-A', 'sshuttle-t-1024', '-j', 'TPROXY',
|
||||||
'--tproxy-mark', '0x1/0x1', '--dest', u'2404:6800:4004:80c::/64',
|
'--tproxy-mark', '0x01', '--dest',
|
||||||
|
u'2404:6800:4004:80c::/64',
|
||||||
'-m', 'udp', '-p', 'udp', '--dport', '8000:9000',
|
'-m', 'udp', '-p', 'udp', '--dport', '8000:9000',
|
||||||
'--on-port', '1024')
|
'--on-port', '1024')
|
||||||
]
|
]
|
||||||
@ -214,7 +216,7 @@ def test_setup_firewall(mock_ipt_chain_exists, mock_ipt_ttl, mock_ipt):
|
|||||||
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
(AF_INET, 32, True, u'1.2.3.66', 80, 80)],
|
||||||
True,
|
True,
|
||||||
None,
|
None,
|
||||||
63)
|
63, '0x01')
|
||||||
assert mock_ipt_chain_exists.mock_calls == [
|
assert mock_ipt_chain_exists.mock_calls == [
|
||||||
call(AF_INET, 'mangle', 'sshuttle-m-1025'),
|
call(AF_INET, 'mangle', 'sshuttle-m-1025'),
|
||||||
call(AF_INET, 'mangle', 'sshuttle-t-1025'),
|
call(AF_INET, 'mangle', 'sshuttle-t-1025'),
|
||||||
@ -244,17 +246,17 @@ def test_setup_firewall(mock_ipt_chain_exists, mock_ipt_ttl, mock_ipt):
|
|||||||
call(AF_INET, 'mangle', '-A', 'sshuttle-m-1025', '-j', 'RETURN',
|
call(AF_INET, 'mangle', '-A', 'sshuttle-m-1025', '-j', 'RETURN',
|
||||||
'-m', 'addrtype', '--dst-type', 'LOCAL'),
|
'-m', 'addrtype', '--dst-type', 'LOCAL'),
|
||||||
call(AF_INET, 'mangle', '-A', 'sshuttle-d-1025',
|
call(AF_INET, 'mangle', '-A', 'sshuttle-d-1025',
|
||||||
'-j', 'MARK', '--set-mark', '1'),
|
'-j', 'MARK', '--set-mark', '0x01'),
|
||||||
call(AF_INET, 'mangle', '-A', 'sshuttle-d-1025', '-j', 'ACCEPT'),
|
call(AF_INET, 'mangle', '-A', 'sshuttle-d-1025', '-j', 'ACCEPT'),
|
||||||
call(AF_INET, 'mangle', '-A', 'sshuttle-t-1025', '-m', 'socket',
|
call(AF_INET, 'mangle', '-A', 'sshuttle-t-1025', '-m', 'socket',
|
||||||
'-j', 'sshuttle-d-1025', '-m', 'tcp', '-p', 'tcp'),
|
'-j', 'sshuttle-d-1025', '-m', 'tcp', '-p', 'tcp'),
|
||||||
call(AF_INET, 'mangle', '-A', 'sshuttle-t-1025', '-m', 'socket',
|
call(AF_INET, 'mangle', '-A', 'sshuttle-t-1025', '-m', 'socket',
|
||||||
'-j', 'sshuttle-d-1025', '-m', 'udp', '-p', 'udp'),
|
'-j', 'sshuttle-d-1025', '-m', 'udp', '-p', 'udp'),
|
||||||
call(AF_INET, 'mangle', '-A', 'sshuttle-m-1025', '-j', 'MARK',
|
call(AF_INET, 'mangle', '-A', 'sshuttle-m-1025', '-j', 'MARK',
|
||||||
'--set-mark', '1', '--dest', u'1.2.3.33/32',
|
'--set-mark', '0x01', '--dest', u'1.2.3.33/32',
|
||||||
'-m', 'udp', '-p', 'udp', '--dport', '53'),
|
'-m', 'udp', '-p', 'udp', '--dport', '53'),
|
||||||
call(AF_INET, 'mangle', '-A', 'sshuttle-t-1025', '-j', 'TPROXY',
|
call(AF_INET, 'mangle', '-A', 'sshuttle-t-1025', '-j', 'TPROXY',
|
||||||
'--tproxy-mark', '0x1/0x1', '--dest', u'1.2.3.33/32',
|
'--tproxy-mark', '0x01', '--dest', u'1.2.3.33/32',
|
||||||
'-m', 'udp', '-p', 'udp', '--dport', '53', '--on-port', '1027'),
|
'-m', 'udp', '-p', 'udp', '--dport', '53', '--on-port', '1027'),
|
||||||
call(AF_INET, 'mangle', '-A', 'sshuttle-m-1025', '-j', 'RETURN',
|
call(AF_INET, 'mangle', '-A', 'sshuttle-m-1025', '-j', 'RETURN',
|
||||||
'--dest', u'1.2.3.66/32', '-m', 'tcp', '-p', 'tcp',
|
'--dest', u'1.2.3.66/32', '-m', 'tcp', '-p', 'tcp',
|
||||||
@ -269,16 +271,16 @@ def test_setup_firewall(mock_ipt_chain_exists, mock_ipt_ttl, mock_ipt):
|
|||||||
'--dest', u'1.2.3.66/32', '-m', 'udp', '-p', 'udp',
|
'--dest', u'1.2.3.66/32', '-m', 'udp', '-p', 'udp',
|
||||||
'--dport', '80:80'),
|
'--dport', '80:80'),
|
||||||
call(AF_INET, 'mangle', '-A', 'sshuttle-m-1025', '-j', 'MARK',
|
call(AF_INET, 'mangle', '-A', 'sshuttle-m-1025', '-j', 'MARK',
|
||||||
'--set-mark', '1', '--dest', u'1.2.3.0/24',
|
'--set-mark', '0x01', '--dest', u'1.2.3.0/24',
|
||||||
'-m', 'tcp', '-p', 'tcp'),
|
'-m', 'tcp', '-p', 'tcp'),
|
||||||
call(AF_INET, 'mangle', '-A', 'sshuttle-t-1025', '-j', 'TPROXY',
|
call(AF_INET, 'mangle', '-A', 'sshuttle-t-1025', '-j', 'TPROXY',
|
||||||
'--tproxy-mark', '0x1/0x1', '--dest', u'1.2.3.0/24',
|
'--tproxy-mark', '0x01', '--dest', u'1.2.3.0/24',
|
||||||
'-m', 'tcp', '-p', 'tcp', '--on-port', '1025'),
|
'-m', 'tcp', '-p', 'tcp', '--on-port', '1025'),
|
||||||
call(AF_INET, 'mangle', '-A', 'sshuttle-m-1025', '-j', 'MARK',
|
call(AF_INET, 'mangle', '-A', 'sshuttle-m-1025', '-j', 'MARK',
|
||||||
'--set-mark', '1', '--dest', u'1.2.3.0/24',
|
'--set-mark', '0x01', '--dest', u'1.2.3.0/24',
|
||||||
'-m', 'udp', '-p', 'udp'),
|
'-m', 'udp', '-p', 'udp'),
|
||||||
call(AF_INET, 'mangle', '-A', 'sshuttle-t-1025', '-j', 'TPROXY',
|
call(AF_INET, 'mangle', '-A', 'sshuttle-t-1025', '-j', 'TPROXY',
|
||||||
'--tproxy-mark', '0x1/0x1', '--dest', u'1.2.3.0/24',
|
'--tproxy-mark', '0x01', '--dest', u'1.2.3.0/24',
|
||||||
'-m', 'udp', '-p', 'udp', '--on-port', '1025')
|
'-m', 'udp', '-p', 'udp', '--on-port', '1025')
|
||||||
]
|
]
|
||||||
mock_ipt_chain_exists.reset_mock()
|
mock_ipt_chain_exists.reset_mock()
|
||||||
|
Loading…
Reference in New Issue
Block a user