mirror of
https://github.com/sshuttle/sshuttle.git
synced 2025-07-06 09:40:32 +02:00
Compare commits
30 Commits
Author | SHA1 | Date | |
---|---|---|---|
752a953101 | |||
61f4cd9de5 | |||
8e35f049e2 | |||
0e99adc5d1 | |||
04849df7e3 | |||
531a17c151 | |||
d43db80dec | |||
0b1a260436 | |||
efc854c33e | |||
ca41026c89 | |||
b473b91633 | |||
7a54d12f80 | |||
d4bbf3b68d | |||
41f5b3e9c1 | |||
c780597de3 | |||
d085a419b2 | |||
842768f9cf | |||
97ed2030f3 | |||
6dc368bde8 | |||
f528bb9846 | |||
561b648e4b | |||
0dba8a8beb | |||
7b6f082454 | |||
1ec17e1b1b | |||
cecccc2efd | |||
db69ba6d8d | |||
2bb92cd6d4 | |||
ae5bd28dcf | |||
55bd78fd43 | |||
1f5ed9c66e |
29
CHANGES.rst
29
CHANGES.rst
@ -9,6 +9,35 @@ adheres to `Semantic Versioning`_.
|
|||||||
.. _`Semantic Versioning`: http://semver.org/
|
.. _`Semantic Versioning`: http://semver.org/
|
||||||
|
|
||||||
|
|
||||||
|
0.78.5 - 2019-01-28
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Added
|
||||||
|
-----
|
||||||
|
* doas support as replacmeent for sudo on OpenBSD.
|
||||||
|
* Added ChromeOS section to documentation (#262)
|
||||||
|
* Add --no-sudo-pythonpath option
|
||||||
|
|
||||||
|
Fixed
|
||||||
|
~~~~~
|
||||||
|
* Fix forwarding to a single port.
|
||||||
|
* Various updates to documentation.
|
||||||
|
* Don't crash if we can't look up peername
|
||||||
|
* Fix missing string formatting argument
|
||||||
|
* Moved sshuttle/tests into tests.
|
||||||
|
* Updated bandit config.
|
||||||
|
* Replace path /dev/null by os.devnull.
|
||||||
|
* Added coverage report to tests.
|
||||||
|
* Fixes support for OpenBSD (6.1+) (#282).
|
||||||
|
* Close stdin, stdout, and stderr when using syslog or forking to daemon (#283).
|
||||||
|
* Changes pf exclusion rules precedence.
|
||||||
|
* Fix deadlock with iptables with large ruleset.
|
||||||
|
* docs: document --ns-hosts --to-ns and update --dns.
|
||||||
|
* Use subprocess.check_output instead of run.
|
||||||
|
* Fix potential deadlock condition in nft_get_handle.
|
||||||
|
* auto-nets: retrieve routes only if using auto-nets.
|
||||||
|
|
||||||
|
|
||||||
0.78.4 - 2018-04-02
|
0.78.4 - 2018-04-02
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ It is also possible to install into a virtualenv as a non-root user.
|
|||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
The documentation for the stable version is available at:
|
The documentation for the stable version is available at:
|
||||||
http://sshuttle.readthedocs.org/
|
https://sshuttle.readthedocs.org/
|
||||||
|
|
||||||
The documentation for the latest development version is available at:
|
The documentation for the latest development version is available at:
|
||||||
http://sshuttle.readthedocs.org/en/latest/
|
https://sshuttle.readthedocs.org/en/latest/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
exclude_dirs:
|
exclude_dirs:
|
||||||
- sshuttle/tests
|
- tests
|
||||||
skips:
|
skips:
|
||||||
- B101
|
- B101
|
||||||
- B104
|
- B104
|
||||||
|
12
docs/chromeos.rst
Normal file
12
docs/chromeos.rst
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
Google ChromeOS
|
||||||
|
===============
|
||||||
|
|
||||||
|
Currently there is no built in support for running sshuttle directly on
|
||||||
|
Google ChromeOS/Chromebooks.
|
||||||
|
|
||||||
|
What we can really do is to create a Linux VM with Crostini. In the default
|
||||||
|
stretch/Debian 9 VM, you can then install sshuttle as on any Linux box and
|
||||||
|
it just works, as do xterms and ssvncviewer etc.
|
||||||
|
|
||||||
|
https://www.reddit.com/r/Crostini/wiki/getstarted/crostini-setup-guide
|
||||||
|
|
@ -94,7 +94,30 @@ Options
|
|||||||
.. option:: --dns
|
.. option:: --dns
|
||||||
|
|
||||||
Capture local DNS requests and forward to the remote DNS
|
Capture local DNS requests and forward to the remote DNS
|
||||||
server.
|
server. All queries to any of the local system's DNS
|
||||||
|
servers (/etc/resolv.conf) will be intercepted and
|
||||||
|
resolved on the remote side of the tunnel instead, there
|
||||||
|
using the DNS specified via the :option:`--to-ns=` option,
|
||||||
|
if specified.
|
||||||
|
|
||||||
|
.. option:: --ns-hosts=server1[,server2[,server3[...]]]
|
||||||
|
|
||||||
|
Capture local DNS requests to the specified server(s)
|
||||||
|
and forward to the remote DNS server. Contrary to the
|
||||||
|
:option:`--dns` option, this flag allows to specify the
|
||||||
|
DNS server(s) the queries to which to intercept,
|
||||||
|
instead of intercepting all DNS traffic on the local
|
||||||
|
machine. This can be useful when only certain DNS
|
||||||
|
requests should be resolved on the remote side of the
|
||||||
|
tunnel, e.g. in combination with dnsmasq.
|
||||||
|
|
||||||
|
.. option:: --to-ns=server
|
||||||
|
|
||||||
|
The DNS to forward requests to when remote DNS
|
||||||
|
resolution is enabled. If not given, sshuttle will
|
||||||
|
simply resolve using the system configured resolver on
|
||||||
|
the remote side (via /etc/resolv.conf on the remote
|
||||||
|
side).
|
||||||
|
|
||||||
.. option:: --python
|
.. option:: --python
|
||||||
|
|
||||||
@ -204,17 +227,21 @@ Options
|
|||||||
makes it a lot easier to debug and test the :option:`--auto-hosts`
|
makes it a lot easier to debug and test the :option:`--auto-hosts`
|
||||||
feature.
|
feature.
|
||||||
|
|
||||||
|
.. option:: --version
|
||||||
|
|
||||||
|
Print program version.
|
||||||
|
|
||||||
|
|
||||||
Configuration File
|
Configuration File
|
||||||
------------------
|
------------------
|
||||||
All the options described above can optionally be specified in a configuration
|
All the options described above can optionally be specified in a configuration
|
||||||
file.
|
file.
|
||||||
|
|
||||||
To run :program:`sshuttle` with options defined in, e.g., `/etc/ssshuttle.conf`
|
To run :program:`sshuttle` with options defined in, e.g., `/etc/sshuttle.conf`
|
||||||
just pass the path to the file preceded by the `@` character, e.g.
|
just pass the path to the file preceded by the `@` character, e.g.
|
||||||
:option:`@/etc/ssshuttle.conf`.
|
:option:`@/etc/sshuttle.conf`.
|
||||||
|
|
||||||
When running :program:`sshuttle` with options defined in a configuratio file,
|
When running :program:`sshuttle` with options defined in a configuration file,
|
||||||
options can still be passed via the command line in addition to what is
|
options can still be passed via the command line in addition to what is
|
||||||
defined in the file. If a given option is defined both in the file and in
|
defined in the file. If a given option is defined both in the file and in
|
||||||
the command line, the value in the command line will take precedence.
|
the command line, the value in the command line will take precedence.
|
||||||
|
@ -6,5 +6,6 @@ Contents:
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
chromeos
|
||||||
tproxy
|
tproxy
|
||||||
windows
|
windows
|
||||||
|
@ -73,8 +73,6 @@ possible as support for older versions might be dropped in the future.
|
|||||||
Additional Suggested Software
|
Additional Suggested Software
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
- You may want to use autossh, available in various package management
|
|
||||||
systems.
|
|
||||||
- If you are using systemd, sshuttle can notify it when the connection to
|
- If you are using systemd, sshuttle can notify it when the connection to
|
||||||
the remote end is established and the firewall rules are installed. For
|
the remote end is established and the firewall rules are installed. For
|
||||||
this feature to work you must configure the process start-up type for the
|
this feature to work you must configure the process start-up type for the
|
||||||
@ -89,6 +87,7 @@ Additional Suggested Software
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=notify
|
Type=notify
|
||||||
|
NotifyAccess=all
|
||||||
ExecStart=/usr/bin/sshuttle --dns --remote <user>@<server> <subnets...>
|
ExecStart=/usr/bin/sshuttle --dns --remote <user>@<server> <subnets...>
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
-r requirements.txt
|
-r requirements.txt
|
||||||
pytest==3.4.2
|
pytest==3.4.2
|
||||||
|
pytest-cov==2.6.0
|
||||||
mock==2.0.0
|
mock==2.0.0
|
||||||
flake8==3.5.0
|
flake8==3.5.0
|
||||||
|
@ -7,3 +7,6 @@ universal = 1
|
|||||||
[upload]
|
[upload]
|
||||||
sign=true
|
sign=true
|
||||||
identity=0x1784577F811F6EAC
|
identity=0x1784577F811F6EAC
|
||||||
|
|
||||||
|
[tool:pytest]
|
||||||
|
addopts = --cov=sshuttle --cov-branch --cov-report=term-missing
|
||||||
|
8
setup.py
8
setup.py
@ -57,6 +57,12 @@ setup(
|
|||||||
'sshuttle = sshuttle.cmdline:main',
|
'sshuttle = sshuttle.cmdline:main',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
tests_require=['pytest', 'pytest-runner', 'mock'],
|
tests_require=[
|
||||||
|
'pytest',
|
||||||
|
'pytest-cov',
|
||||||
|
'pytest-runner',
|
||||||
|
'mock',
|
||||||
|
'flake8',
|
||||||
|
],
|
||||||
keywords="ssh vpn",
|
keywords="ssh vpn",
|
||||||
)
|
)
|
||||||
|
@ -35,4 +35,5 @@ sshuttle.helpers.verbose = verbosity
|
|||||||
|
|
||||||
import sshuttle.cmdline_options as options
|
import sshuttle.cmdline_options as options
|
||||||
from sshuttle.server import main
|
from sshuttle.server import main
|
||||||
main(options.latency_control, options.auto_hosts, options.to_nameserver)
|
main(options.latency_control, options.auto_hosts, options.to_nameserver,
|
||||||
|
options.auto_nets)
|
||||||
|
@ -33,7 +33,7 @@ except AttributeError:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
_extra_fd = os.open('/dev/null', os.O_RDONLY)
|
_extra_fd = os.open(os.devnull, os.O_RDONLY)
|
||||||
|
|
||||||
|
|
||||||
def got_signal(signum, frame):
|
def got_signal(signum, frame):
|
||||||
@ -93,7 +93,7 @@ def daemonize():
|
|||||||
# be deleted.
|
# be deleted.
|
||||||
signal.signal(signal.SIGTERM, got_signal)
|
signal.signal(signal.SIGTERM, got_signal)
|
||||||
|
|
||||||
si = open('/dev/null', 'r+')
|
si = open(os.devnull, 'r+')
|
||||||
os.dup2(si.fileno(), 0)
|
os.dup2(si.fileno(), 0)
|
||||||
os.dup2(si.fileno(), 1)
|
os.dup2(si.fileno(), 1)
|
||||||
si.close()
|
si.close()
|
||||||
@ -183,7 +183,13 @@ class MultiListener:
|
|||||||
|
|
||||||
class FirewallClient:
|
class FirewallClient:
|
||||||
|
|
||||||
def __init__(self, method_name):
|
def __init__(self, method_name, sudo_pythonpath):
|
||||||
|
|
||||||
|
# Default to sudo unless on OpenBSD in which case use built in `doas`
|
||||||
|
elevbin = 'sudo'
|
||||||
|
if platform.platform().startswith('OpenBSD'):
|
||||||
|
elevbin = 'doas'
|
||||||
|
|
||||||
self.auto_nets = []
|
self.auto_nets = []
|
||||||
python_path = os.path.dirname(os.path.dirname(__file__))
|
python_path = os.path.dirname(os.path.dirname(__file__))
|
||||||
argvbase = ([sys.executable, sys.argv[0]] +
|
argvbase = ([sys.executable, sys.argv[0]] +
|
||||||
@ -192,11 +198,13 @@ class FirewallClient:
|
|||||||
['--firewall'])
|
['--firewall'])
|
||||||
if ssyslog._p:
|
if ssyslog._p:
|
||||||
argvbase += ['--syslog']
|
argvbase += ['--syslog']
|
||||||
argv_tries = [
|
elev_prefix = [part % {'eb': elevbin}
|
||||||
['sudo', '-p', '[local sudo] Password: ', '/usr/bin/env',
|
for part in ['%(eb)s', '-p',
|
||||||
('PYTHONPATH=%s' % python_path)] + argvbase,
|
'[local %(eb)s] Password: ']]
|
||||||
argvbase
|
if sudo_pythonpath:
|
||||||
]
|
elev_prefix += ['/usr/bin/env',
|
||||||
|
'PYTHONPATH=%s' % python_path]
|
||||||
|
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,
|
||||||
# because stupid Linux 'su' requires that stdin be attached to a tty.
|
# because stupid Linux 'su' requires that stdin be attached to a tty.
|
||||||
@ -347,7 +355,7 @@ def onaccept_tcp(listener, method, mux, handlers):
|
|||||||
sock, srcip = listener.accept()
|
sock, srcip = listener.accept()
|
||||||
sock.close()
|
sock.close()
|
||||||
finally:
|
finally:
|
||||||
_extra_fd = os.open('/dev/null', os.O_RDONLY)
|
_extra_fd = os.open(os.devnull, os.O_RDONLY)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
@ -445,7 +453,8 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
|
|||||||
stderr=ssyslog._p and ssyslog._p.stdin,
|
stderr=ssyslog._p and ssyslog._p.stdin,
|
||||||
options=dict(latency_control=latency_control,
|
options=dict(latency_control=latency_control,
|
||||||
auto_hosts=auto_hosts,
|
auto_hosts=auto_hosts,
|
||||||
to_nameserver=to_nameserver))
|
to_nameserver=to_nameserver,
|
||||||
|
auto_nets=auto_nets))
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
if e.args[0] == errno.EPIPE:
|
if e.args[0] == errno.EPIPE:
|
||||||
raise Fatal("failed to establish ssh session (1)")
|
raise Fatal("failed to establish ssh session (1)")
|
||||||
@ -544,7 +553,7 @@ def main(listenip_v6, listenip_v4,
|
|||||||
ssh_cmd, remotename, python, latency_control, dns, nslist,
|
ssh_cmd, remotename, python, latency_control, dns, nslist,
|
||||||
method_name, seed_hosts, auto_hosts, auto_nets,
|
method_name, seed_hosts, auto_hosts, auto_nets,
|
||||||
subnets_include, subnets_exclude, daemon, to_nameserver, pidfile,
|
subnets_include, subnets_exclude, daemon, to_nameserver, pidfile,
|
||||||
user):
|
user, sudo_pythonpath):
|
||||||
|
|
||||||
if daemon:
|
if daemon:
|
||||||
try:
|
try:
|
||||||
@ -554,7 +563,7 @@ def main(listenip_v6, listenip_v4,
|
|||||||
return 5
|
return 5
|
||||||
debug1('Starting sshuttle proxy.\n')
|
debug1('Starting sshuttle proxy.\n')
|
||||||
|
|
||||||
fw = FirewallClient(method_name)
|
fw = FirewallClient(method_name, sudo_pythonpath)
|
||||||
|
|
||||||
# Get family specific subnet lists
|
# Get family specific subnet lists
|
||||||
if dns:
|
if dns:
|
||||||
|
@ -59,6 +59,8 @@ def main():
|
|||||||
ipport_v6 = "auto" if not opt.disable_ipv6 else None
|
ipport_v6 = "auto" if not opt.disable_ipv6 else None
|
||||||
if opt.syslog:
|
if opt.syslog:
|
||||||
ssyslog.start_syslog()
|
ssyslog.start_syslog()
|
||||||
|
ssyslog.close_stdin()
|
||||||
|
ssyslog.stdout_to_syslog()
|
||||||
ssyslog.stderr_to_syslog()
|
ssyslog.stderr_to_syslog()
|
||||||
return_code = client.main(ipport_v6, ipport_v4,
|
return_code = client.main(ipport_v6, ipport_v4,
|
||||||
opt.ssh_cmd,
|
opt.ssh_cmd,
|
||||||
@ -76,12 +78,13 @@ def main():
|
|||||||
opt.daemon,
|
opt.daemon,
|
||||||
opt.to_ns,
|
opt.to_ns,
|
||||||
opt.pidfile,
|
opt.pidfile,
|
||||||
opt.user)
|
opt.user,
|
||||||
|
opt.sudo_pythonpath)
|
||||||
|
|
||||||
if return_code == 0:
|
if return_code == 0:
|
||||||
log('Normal exit code, exiting...')
|
log('Normal exit code, exiting...')
|
||||||
else:
|
else:
|
||||||
log('Abnormal exit code detected, failing...' % return_code)
|
log('Abnormal exit code %d detected, failing...' % return_code)
|
||||||
return return_code
|
return return_code
|
||||||
|
|
||||||
except Fatal as e:
|
except Fatal as e:
|
||||||
|
@ -21,7 +21,7 @@ _smb_ok = True
|
|||||||
hostnames = {}
|
hostnames = {}
|
||||||
queue = {}
|
queue = {}
|
||||||
try:
|
try:
|
||||||
null = open('/dev/null', 'wb')
|
null = open(os.devnull, 'wb')
|
||||||
except IOError:
|
except IOError:
|
||||||
_, e = sys.exc_info()[:2]
|
_, e = sys.exc_info()[:2]
|
||||||
log('warning: %s\n' % e)
|
log('warning: %s\n' % e)
|
||||||
|
@ -24,13 +24,13 @@ def ipt_chain_exists(family, table, name):
|
|||||||
'PATH': os.environ['PATH'],
|
'PATH': os.environ['PATH'],
|
||||||
'LC_ALL': "C",
|
'LC_ALL': "C",
|
||||||
}
|
}
|
||||||
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, env=env)
|
try:
|
||||||
for line in p.stdout:
|
output = ssubprocess.check_output(argv, env=env)
|
||||||
if line.startswith(b'Chain %s ' % name.encode("ASCII")):
|
for line in output.decode('ASCII').split('\n'):
|
||||||
|
if line.startswith('Chain %s ' % name):
|
||||||
return True
|
return True
|
||||||
rv = p.wait()
|
except ssubprocess.CalledProcessError as e:
|
||||||
if rv:
|
raise Fatal('%r returned %d' % (argv, e.returncode))
|
||||||
raise Fatal('%r returned %d' % (argv, rv))
|
|
||||||
|
|
||||||
|
|
||||||
def ipt(family, table, *args):
|
def ipt(family, table, *args):
|
||||||
@ -74,13 +74,13 @@ def nft_get_handle(expression, chain):
|
|||||||
'PATH': os.environ['PATH'],
|
'PATH': os.environ['PATH'],
|
||||||
'LC_ALL': "C",
|
'LC_ALL': "C",
|
||||||
}
|
}
|
||||||
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, env=env)
|
try:
|
||||||
for line in p.stdout:
|
output = ssubprocess.check_output(argv, env=env)
|
||||||
if (b'jump %s' % chain.encode('utf-8')) in line:
|
for line in output.decode('utf-8').split('\n'):
|
||||||
return re.sub('.*# ', '', line.decode('utf-8'))
|
if ('jump %s' % chain) in line:
|
||||||
rv = p.wait()
|
return re.sub('.*# ', '', line)
|
||||||
if rv:
|
except ssubprocess.CalledProcessError as e:
|
||||||
raise Fatal('%r returned %d' % (argv, rv))
|
raise Fatal('%r returned %d' % (argv, e.returncode))
|
||||||
|
|
||||||
|
|
||||||
_no_ttl_module = False
|
_no_ttl_module = False
|
||||||
|
@ -105,7 +105,7 @@ def _fill_oldctls(prefix):
|
|||||||
def _sysctl_set(name, val):
|
def _sysctl_set(name, val):
|
||||||
argv = ['sysctl', '-w', '%s=%s' % (name, val)]
|
argv = ['sysctl', '-w', '%s=%s' % (name, val)]
|
||||||
debug1('>> %s\n' % ' '.join(argv))
|
debug1('>> %s\n' % ' '.join(argv))
|
||||||
return ssubprocess.call(argv, stdout=open('/dev/null', 'w'))
|
return ssubprocess.call(argv, stdout=open(os.devnull, 'w'))
|
||||||
|
|
||||||
|
|
||||||
_changedctls = []
|
_changedctls = []
|
||||||
|
@ -40,8 +40,12 @@ class Method(BaseMethod):
|
|||||||
for _, swidth, sexclude, snet, fport, lport \
|
for _, swidth, sexclude, snet, fport, lport \
|
||||||
in sorted(subnets, key=subnet_weight, reverse=True):
|
in sorted(subnets, key=subnet_weight, reverse=True):
|
||||||
tcp_ports = ('ip', 'protocol', 'tcp')
|
tcp_ports = ('ip', 'protocol', 'tcp')
|
||||||
if fport:
|
if fport and fport != lport:
|
||||||
tcp_ports = tcp_ports + ('dport { %d-%d }' % (fport, lport))
|
tcp_ports = \
|
||||||
|
tcp_ports + \
|
||||||
|
('tcp', 'dport', '{ %d-%d }' % (fport, lport))
|
||||||
|
elif fport and fport == lport:
|
||||||
|
tcp_ports = tcp_ports + ('tcp', 'dport', '%d' % (fport))
|
||||||
|
|
||||||
if sexclude:
|
if sexclude:
|
||||||
_nft('add rule', chain, *(tcp_ports + (
|
_nft('add rule', chain, *(tcp_ports + (
|
||||||
|
@ -217,7 +217,7 @@ class FreeBsd(Generic):
|
|||||||
b'pass out route-to lo0 %s proto tcp '
|
b'pass out route-to lo0 %s proto tcp '
|
||||||
b'to %s keep state' % (inet_version, subnet)
|
b'to %s keep state' % (inet_version, subnet)
|
||||||
if not exclude else
|
if not exclude else
|
||||||
b'pass out quick %s proto tcp to %s' % (inet_version, subnet)
|
b'pass out %s proto tcp to %s' % (inet_version, subnet)
|
||||||
for exclude, subnet in includes
|
for exclude, subnet in includes
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -261,7 +261,7 @@ class OpenBsd(Generic):
|
|||||||
("proto_variant", c_uint8),
|
("proto_variant", c_uint8),
|
||||||
("direction", c_uint8)]
|
("direction", c_uint8)]
|
||||||
|
|
||||||
self.pfioc_rule = c_char * 3400
|
self.pfioc_rule = c_char * 3416
|
||||||
self.pfioc_natlook = pfioc_natlook
|
self.pfioc_natlook = pfioc_natlook
|
||||||
super(OpenBsd, self).__init__()
|
super(OpenBsd, self).__init__()
|
||||||
|
|
||||||
@ -287,7 +287,7 @@ class OpenBsd(Generic):
|
|||||||
b'pass out %s proto tcp to %s '
|
b'pass out %s proto tcp to %s '
|
||||||
b'route-to lo0 keep state' % (inet_version, subnet)
|
b'route-to lo0 keep state' % (inet_version, subnet)
|
||||||
if not exclude else
|
if not exclude else
|
||||||
b'pass out quick %s proto tcp to %s' % (inet_version, subnet)
|
b'pass out %s proto tcp to %s' % (inet_version, subnet)
|
||||||
for exclude, subnet in includes
|
for exclude, subnet in includes
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -452,7 +452,7 @@ class Method(BaseMethod):
|
|||||||
# exclusion first; the table will ignore the second, opposite
|
# exclusion first; the table will ignore the second, opposite
|
||||||
# definition
|
# definition
|
||||||
for _, swidth, sexclude, snet, fport, lport \
|
for _, swidth, sexclude, snet, fport, lport \
|
||||||
in sorted(subnets, key=subnet_weight, reverse=True):
|
in sorted(subnets, key=subnet_weight):
|
||||||
includes.append((sexclude, b"%s/%d%s" % (
|
includes.append((sexclude, b"%s/%d%s" % (
|
||||||
snet.encode("ASCII"),
|
snet.encode("ASCII"),
|
||||||
swidth,
|
swidth,
|
||||||
|
@ -310,3 +310,11 @@ parser.add_argument(
|
|||||||
(internal use only)
|
(internal use only)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--no-sudo-pythonpath",
|
||||||
|
action="store_false",
|
||||||
|
dest="sudo_pythonpath",
|
||||||
|
help="""
|
||||||
|
do not set PYTHONPATH when invoking sudo
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
@ -279,7 +279,7 @@ class UdpProxy(Handler):
|
|||||||
self.mux.send(self.chan, ssnet.CMD_UDP_DATA, hdr + data)
|
self.mux.send(self.chan, ssnet.CMD_UDP_DATA, hdr + data)
|
||||||
|
|
||||||
|
|
||||||
def main(latency_control, auto_hosts, to_nameserver):
|
def main(latency_control, auto_hosts, to_nameserver, auto_nets):
|
||||||
debug1('Starting server with Python version %s\n'
|
debug1('Starting server with Python version %s\n'
|
||||||
% platform.python_version())
|
% platform.python_version())
|
||||||
|
|
||||||
@ -289,10 +289,6 @@ def main(latency_control, auto_hosts, to_nameserver):
|
|||||||
helpers.logprefix = 'server: '
|
helpers.logprefix = 'server: '
|
||||||
debug1('latency control setting = %r\n' % latency_control)
|
debug1('latency control setting = %r\n' % latency_control)
|
||||||
|
|
||||||
routes = list(list_routes())
|
|
||||||
debug1('available routes:\n')
|
|
||||||
for r in routes:
|
|
||||||
debug1(' %d/%s/%d\n' % r)
|
|
||||||
|
|
||||||
# synchronization header
|
# synchronization header
|
||||||
sys.stdout.write('\0\0SSHUTTLE0001')
|
sys.stdout.write('\0\0SSHUTTLE0001')
|
||||||
@ -304,6 +300,16 @@ def main(latency_control, auto_hosts, to_nameserver):
|
|||||||
socket.fromfd(sys.stdout.fileno(),
|
socket.fromfd(sys.stdout.fileno(),
|
||||||
socket.AF_INET, socket.SOCK_STREAM))
|
socket.AF_INET, socket.SOCK_STREAM))
|
||||||
handlers.append(mux)
|
handlers.append(mux)
|
||||||
|
|
||||||
|
debug1('auto-nets:' + str(auto_nets) + '\n')
|
||||||
|
if auto_nets:
|
||||||
|
routes = list(list_routes())
|
||||||
|
debug1('available routes:\n')
|
||||||
|
for r in routes:
|
||||||
|
debug1(' %d/%s/%d\n' % r)
|
||||||
|
else:
|
||||||
|
routes = []
|
||||||
|
|
||||||
routepkt = ''
|
routepkt = ''
|
||||||
for r in routes:
|
for r in routes:
|
||||||
routepkt += '%d,%s,%d\n' % r
|
routepkt += '%d,%s,%d\n' % r
|
||||||
|
@ -116,8 +116,8 @@ def connect(ssh_cmd, rhostport, python, stderr, options):
|
|||||||
if python:
|
if python:
|
||||||
pycmd = "'%s' -c '%s'" % (python, pyscript)
|
pycmd = "'%s' -c '%s'" % (python, pyscript)
|
||||||
else:
|
else:
|
||||||
pycmd = ("P=python3; $P -V 2>/dev/null || P=python; "
|
pycmd = ("P=python3; $P -V 2>%s || P=python; "
|
||||||
"exec \"$P\" -c %s") % quote(pyscript)
|
"exec \"$P\" -c %s") % (os.devnull, quote(pyscript))
|
||||||
pycmd = ("exec /bin/sh -c %s" % quote(pycmd))
|
pycmd = ("exec /bin/sh -c %s" % quote(pycmd))
|
||||||
argv = (sshl +
|
argv = (sshl +
|
||||||
portl +
|
portl +
|
||||||
|
@ -95,6 +95,8 @@ def _try_peername(sock):
|
|||||||
_, e = sys.exc_info()[:2]
|
_, e = sys.exc_info()[:2]
|
||||||
if e.args[0] not in (errno.ENOTCONN, errno.ENOTSOCK):
|
if e.args[0] not in (errno.ENOTCONN, errno.ENOTSOCK):
|
||||||
raise
|
raise
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
return 'unknown'
|
return 'unknown'
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,12 +8,24 @@ _p = None
|
|||||||
|
|
||||||
def start_syslog():
|
def start_syslog():
|
||||||
global _p
|
global _p
|
||||||
_p = ssubprocess.Popen(['logger',
|
with open(os.devnull, 'w') as devnull:
|
||||||
'-p', 'daemon.notice',
|
_p = ssubprocess.Popen(
|
||||||
'-t', 'sshuttle'], stdin=ssubprocess.PIPE)
|
['logger', '-p', 'daemon.notice', '-t', 'sshuttle'],
|
||||||
|
stdin=ssubprocess.PIPE,
|
||||||
|
stdout=devnull,
|
||||||
|
stderr=devnull
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def close_stdin():
|
||||||
|
sys.stdin.close()
|
||||||
|
|
||||||
|
|
||||||
|
def stdout_to_syslog():
|
||||||
|
sys.stdout.flush()
|
||||||
|
os.dup2(_p.stdin.fileno(), sys.stdout.fileno())
|
||||||
|
|
||||||
|
|
||||||
def stderr_to_syslog():
|
def stderr_to_syslog():
|
||||||
sys.stdout.flush()
|
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
os.dup2(_p.stdin.fileno(), 2)
|
os.dup2(_p.stdin.fileno(), sys.stderr.fileno())
|
||||||
|
@ -205,10 +205,10 @@ def test_setup_firewall_darwin(mock_pf_get_dev, mock_ioctl, mock_pfctl):
|
|||||||
b'2404:6800:4004:80c::/64 port 8000:9000 -> ::1 port 1024\n'
|
b'2404:6800:4004:80c::/64 port 8000:9000 -> ::1 port 1024\n'
|
||||||
b'rdr pass on lo0 inet6 proto udp '
|
b'rdr pass on lo0 inet6 proto udp '
|
||||||
b'to <dns_servers> port 53 -> ::1 port 1026\n'
|
b'to <dns_servers> port 53 -> ::1 port 1026\n'
|
||||||
b'pass out quick inet6 proto tcp to '
|
|
||||||
b'2404:6800:4004:80c::101f/128 port 8080:8080\n'
|
|
||||||
b'pass out route-to lo0 inet6 proto tcp to '
|
b'pass out route-to lo0 inet6 proto tcp to '
|
||||||
b'2404:6800:4004:80c::/64 port 8000:9000 keep state\n'
|
b'2404:6800:4004:80c::/64 port 8000:9000 keep state\n'
|
||||||
|
b'pass out inet6 proto tcp to '
|
||||||
|
b'2404:6800:4004:80c::101f/128 port 8080:8080\n'
|
||||||
b'pass out route-to lo0 inet6 proto udp '
|
b'pass out route-to lo0 inet6 proto udp '
|
||||||
b'to <dns_servers> port 53 keep state\n'),
|
b'to <dns_servers> port 53 keep state\n'),
|
||||||
call('-E'),
|
call('-E'),
|
||||||
@ -257,8 +257,8 @@ def test_setup_firewall_darwin(mock_pf_get_dev, mock_ioctl, mock_pfctl):
|
|||||||
b'-> 127.0.0.1 port 1025\n'
|
b'-> 127.0.0.1 port 1025\n'
|
||||||
b'rdr pass on lo0 inet proto udp '
|
b'rdr pass on lo0 inet proto udp '
|
||||||
b'to <dns_servers> port 53 -> 127.0.0.1 port 1027\n'
|
b'to <dns_servers> port 53 -> 127.0.0.1 port 1027\n'
|
||||||
b'pass out quick inet proto tcp to 1.2.3.66/32 port 80:80\n'
|
|
||||||
b'pass out route-to lo0 inet proto tcp to 1.2.3.0/24 keep state\n'
|
b'pass out route-to lo0 inet proto tcp to 1.2.3.0/24 keep state\n'
|
||||||
|
b'pass out inet proto tcp to 1.2.3.66/32 port 80:80\n'
|
||||||
b'pass out route-to lo0 inet proto udp '
|
b'pass out route-to lo0 inet proto udp '
|
||||||
b'to <dns_servers> port 53 keep state\n'),
|
b'to <dns_servers> port 53 keep state\n'),
|
||||||
call('-E'),
|
call('-E'),
|
||||||
@ -308,10 +308,10 @@ def test_setup_firewall_freebsd(mock_pf_get_dev, mock_ioctl, mock_pfctl,
|
|||||||
b'2404:6800:4004:80c::/64 port 8000:9000 -> ::1 port 1024\n'
|
b'2404:6800:4004:80c::/64 port 8000:9000 -> ::1 port 1024\n'
|
||||||
b'rdr pass on lo0 inet6 proto udp '
|
b'rdr pass on lo0 inet6 proto udp '
|
||||||
b'to <dns_servers> port 53 -> ::1 port 1026\n'
|
b'to <dns_servers> port 53 -> ::1 port 1026\n'
|
||||||
b'pass out quick inet6 proto tcp to '
|
|
||||||
b'2404:6800:4004:80c::101f/128 port 8080:8080\n'
|
|
||||||
b'pass out route-to lo0 inet6 proto tcp to '
|
b'pass out route-to lo0 inet6 proto tcp to '
|
||||||
b'2404:6800:4004:80c::/64 port 8000:9000 keep state\n'
|
b'2404:6800:4004:80c::/64 port 8000:9000 keep state\n'
|
||||||
|
b'pass out inet6 proto tcp to '
|
||||||
|
b'2404:6800:4004:80c::101f/128 port 8080:8080\n'
|
||||||
b'pass out route-to lo0 inet6 proto udp '
|
b'pass out route-to lo0 inet6 proto udp '
|
||||||
b'to <dns_servers> port 53 keep state\n'),
|
b'to <dns_servers> port 53 keep state\n'),
|
||||||
call('-e'),
|
call('-e'),
|
||||||
@ -359,8 +359,8 @@ def test_setup_firewall_freebsd(mock_pf_get_dev, mock_ioctl, mock_pfctl,
|
|||||||
b'to 1.2.3.0/24 -> 127.0.0.1 port 1025\n'
|
b'to 1.2.3.0/24 -> 127.0.0.1 port 1025\n'
|
||||||
b'rdr pass on lo0 inet proto udp '
|
b'rdr pass on lo0 inet proto udp '
|
||||||
b'to <dns_servers> port 53 -> 127.0.0.1 port 1027\n'
|
b'to <dns_servers> port 53 -> 127.0.0.1 port 1027\n'
|
||||||
b'pass out quick inet proto tcp to 1.2.3.66/32 port 80:80\n'
|
|
||||||
b'pass out route-to lo0 inet proto tcp to 1.2.3.0/24 keep state\n'
|
b'pass out route-to lo0 inet proto tcp to 1.2.3.0/24 keep state\n'
|
||||||
|
b'pass out inet proto tcp to 1.2.3.66/32 port 80:80\n'
|
||||||
b'pass out route-to lo0 inet proto udp '
|
b'pass out route-to lo0 inet proto udp '
|
||||||
b'to <dns_servers> port 53 keep state\n'),
|
b'to <dns_servers> port 53 keep state\n'),
|
||||||
call('-e'),
|
call('-e'),
|
||||||
@ -403,8 +403,8 @@ def test_setup_firewall_openbsd(mock_pf_get_dev, mock_ioctl, mock_pfctl):
|
|||||||
None)
|
None)
|
||||||
|
|
||||||
assert mock_ioctl.mock_calls == [
|
assert mock_ioctl.mock_calls == [
|
||||||
call(mock_pf_get_dev(), 0xcd48441a, ANY),
|
call(mock_pf_get_dev(), 0xcd58441a, ANY),
|
||||||
call(mock_pf_get_dev(), 0xcd48441a, ANY),
|
call(mock_pf_get_dev(), 0xcd58441a, ANY),
|
||||||
]
|
]
|
||||||
assert mock_pfctl.mock_calls == [
|
assert mock_pfctl.mock_calls == [
|
||||||
call('-s Interfaces -i lo -v'),
|
call('-s Interfaces -i lo -v'),
|
||||||
@ -416,10 +416,10 @@ def test_setup_firewall_openbsd(mock_pf_get_dev, mock_ioctl, mock_pfctl):
|
|||||||
b'port 8000:9000 divert-to ::1 port 1024\n'
|
b'port 8000:9000 divert-to ::1 port 1024\n'
|
||||||
b'pass in on lo0 inet6 proto udp '
|
b'pass in on lo0 inet6 proto udp '
|
||||||
b'to <dns_servers> port 53 rdr-to ::1 port 1026\n'
|
b'to <dns_servers> port 53 rdr-to ::1 port 1026\n'
|
||||||
b'pass out quick inet6 proto tcp to '
|
|
||||||
b'2404:6800:4004:80c::101f/128 port 8080:8080\n'
|
|
||||||
b'pass out inet6 proto tcp to 2404:6800:4004:80c::/64 '
|
b'pass out inet6 proto tcp to 2404:6800:4004:80c::/64 '
|
||||||
b'port 8000:9000 route-to lo0 keep state\n'
|
b'port 8000:9000 route-to lo0 keep state\n'
|
||||||
|
b'pass out inet6 proto tcp to '
|
||||||
|
b'2404:6800:4004:80c::101f/128 port 8080:8080\n'
|
||||||
b'pass out inet6 proto udp to '
|
b'pass out inet6 proto udp to '
|
||||||
b'<dns_servers> port 53 route-to lo0 keep state\n'),
|
b'<dns_servers> port 53 route-to lo0 keep state\n'),
|
||||||
call('-e'),
|
call('-e'),
|
||||||
@ -451,8 +451,8 @@ def test_setup_firewall_openbsd(mock_pf_get_dev, mock_ioctl, mock_pfctl):
|
|||||||
False,
|
False,
|
||||||
None)
|
None)
|
||||||
assert mock_ioctl.mock_calls == [
|
assert mock_ioctl.mock_calls == [
|
||||||
call(mock_pf_get_dev(), 0xcd48441a, ANY),
|
call(mock_pf_get_dev(), 0xcd58441a, ANY),
|
||||||
call(mock_pf_get_dev(), 0xcd48441a, ANY),
|
call(mock_pf_get_dev(), 0xcd58441a, ANY),
|
||||||
]
|
]
|
||||||
assert mock_pfctl.mock_calls == [
|
assert mock_pfctl.mock_calls == [
|
||||||
call('-s Interfaces -i lo -v'),
|
call('-s Interfaces -i lo -v'),
|
||||||
@ -464,8 +464,8 @@ def test_setup_firewall_openbsd(mock_pf_get_dev, mock_ioctl, mock_pfctl):
|
|||||||
b'127.0.0.1 port 1025\n'
|
b'127.0.0.1 port 1025\n'
|
||||||
b'pass in on lo0 inet proto udp to '
|
b'pass in on lo0 inet proto udp to '
|
||||||
b'<dns_servers> port 53 rdr-to 127.0.0.1 port 1027\n'
|
b'<dns_servers> port 53 rdr-to 127.0.0.1 port 1027\n'
|
||||||
b'pass out quick inet proto tcp to 1.2.3.66/32 port 80:80\n'
|
|
||||||
b'pass out inet proto tcp to 1.2.3.0/24 route-to lo0 keep state\n'
|
b'pass out inet proto tcp to 1.2.3.0/24 route-to lo0 keep state\n'
|
||||||
|
b'pass out inet proto tcp to 1.2.3.66/32 port 80:80\n'
|
||||||
b'pass out inet proto udp to '
|
b'pass out inet proto udp to '
|
||||||
b'<dns_servers> port 53 route-to lo0 keep state\n'),
|
b'<dns_servers> port 53 route-to lo0 keep state\n'),
|
||||||
call('-e'),
|
call('-e'),
|
@ -7,4 +7,4 @@ else:
|
|||||||
|
|
||||||
collect_ignore = []
|
collect_ignore = []
|
||||||
if not good_python:
|
if not good_python:
|
||||||
collect_ignore.append("sshuttle/tests/client")
|
collect_ignore.append("client")
|
Reference in New Issue
Block a user