mirror of
https://github.com/sshuttle/sshuttle.git
synced 2024-11-24 17:04:36 +01:00
support server on Windows
This commit is contained in:
parent
ace8642950
commit
51287dc4db
@ -281,7 +281,7 @@ class RWPair:
|
|||||||
class SocketRWShim:
|
class SocketRWShim:
|
||||||
__slots__ = ('_r', '_w', '_on_end', '_s1', '_s2', '_t1', '_t2')
|
__slots__ = ('_r', '_w', '_on_end', '_s1', '_s2', '_t1', '_t2')
|
||||||
|
|
||||||
def __init__(self, r, w, on_end=None) -> None:
|
def __init__(self, r, w, on_end=None):
|
||||||
self._r = r
|
self._r = r
|
||||||
self._w = w
|
self._w = w
|
||||||
self._on_end = on_end
|
self._on_end = on_end
|
||||||
|
@ -14,7 +14,7 @@ import sshuttle.hostwatch as hostwatch
|
|||||||
import subprocess as ssubprocess
|
import subprocess as ssubprocess
|
||||||
from sshuttle.ssnet import Handler, Proxy, Mux, MuxWrapper
|
from sshuttle.ssnet import Handler, Proxy, Mux, MuxWrapper
|
||||||
from sshuttle.helpers import b, log, debug1, debug2, debug3, Fatal, \
|
from sshuttle.helpers import b, log, debug1, debug2, debug3, Fatal, \
|
||||||
resolvconf_random_nameserver, which, get_env
|
resolvconf_random_nameserver, which, get_env, SocketRWShim
|
||||||
|
|
||||||
|
|
||||||
def _ipmatch(ipstr):
|
def _ipmatch(ipstr):
|
||||||
@ -79,6 +79,20 @@ def _route_iproute(line):
|
|||||||
return ipw, int(mask)
|
return ipw, int(mask)
|
||||||
|
|
||||||
|
|
||||||
|
def _route_windows(line):
|
||||||
|
if " On-link " not in line:
|
||||||
|
return None, None
|
||||||
|
dest, net_mask = re.split(r'\s+', line.strip())[:2]
|
||||||
|
if net_mask == "255.255.255.255":
|
||||||
|
return None, None
|
||||||
|
for p in ('127.', '0.', '224.', '169.254.'):
|
||||||
|
if dest.startswith(p):
|
||||||
|
return None, None
|
||||||
|
ipw = _ipmatch(dest)
|
||||||
|
mask = _maskbits(_ipmatch(net_mask))
|
||||||
|
return ipw, mask
|
||||||
|
|
||||||
|
|
||||||
def _list_routes(argv, extract_route):
|
def _list_routes(argv, extract_route):
|
||||||
# FIXME: IPv4 only
|
# FIXME: IPv4 only
|
||||||
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, env=get_env())
|
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, env=get_env())
|
||||||
@ -101,14 +115,17 @@ def _list_routes(argv, extract_route):
|
|||||||
|
|
||||||
|
|
||||||
def list_routes():
|
def list_routes():
|
||||||
if which('ip'):
|
if sys.platform == 'win32':
|
||||||
routes = _list_routes(['ip', 'route'], _route_iproute)
|
routes = _list_routes(['route', 'PRINT', '-4'], _route_windows)
|
||||||
elif which('netstat'):
|
|
||||||
routes = _list_routes(['netstat', '-rn'], _route_netstat)
|
|
||||||
else:
|
else:
|
||||||
log('WARNING: Neither "ip" nor "netstat" were found on the server. '
|
if which('ip'):
|
||||||
'--auto-nets feature will not work.')
|
routes = _list_routes(['ip', 'route'], _route_iproute)
|
||||||
routes = []
|
elif which('netstat'):
|
||||||
|
routes = _list_routes(['netstat', '-rn'], _route_netstat)
|
||||||
|
else:
|
||||||
|
log('WARNING: Neither "ip" nor "netstat" were found on the server. '
|
||||||
|
'--auto-nets feature will not work.')
|
||||||
|
routes = []
|
||||||
|
|
||||||
for (family, ip, width) in routes:
|
for (family, ip, width) in routes:
|
||||||
if not ip.startswith('0.') and not ip.startswith('127.'):
|
if not ip.startswith('0.') and not ip.startswith('127.'):
|
||||||
@ -282,7 +299,16 @@ def main(latency_control, latency_buffer_size, auto_hosts, to_nameserver,
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
handlers = []
|
handlers = []
|
||||||
mux = Mux(io.FileIO(0, mode='r'), io.FileIO(1, mode='w'))
|
# get unbuffered stdin and stdout in binary mode. Equivalent to stdin.buffer/stdout.buffer (Only available in Python 3)
|
||||||
|
r, w = io.FileIO(0, mode='r'), io.FileIO(1, mode='w')
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
def _deferred_exit():
|
||||||
|
time.sleep(1) # give enough time to write logs to stderr
|
||||||
|
os._exit(23)
|
||||||
|
shim = SocketRWShim(r, w, on_end=_deferred_exit)
|
||||||
|
mux = Mux(*shim.makefiles())
|
||||||
|
else:
|
||||||
|
mux = Mux(r, w)
|
||||||
handlers.append(mux)
|
handlers.append(mux)
|
||||||
|
|
||||||
debug1('auto-nets:' + str(auto_nets))
|
debug1('auto-nets:' + str(auto_nets))
|
||||||
|
@ -115,8 +115,8 @@ def connect(ssh_cmd, rhostport, python, stderr, add_cmd_delimiter, options):
|
|||||||
pyscript = r"""
|
pyscript = r"""
|
||||||
import sys, os;
|
import sys, os;
|
||||||
verbosity=%d;
|
verbosity=%d;
|
||||||
stdin = os.fdopen(0, "rb");
|
stdin = os.fdopen(0, 'rb');
|
||||||
exec(compile(stdin.read(%d), "assembler.py", "exec"));
|
exec(compile(stdin.read(%d), 'assembler.py', 'exec'));
|
||||||
sys.exit(98);
|
sys.exit(98);
|
||||||
""" % (helpers.verbose or 0, len(content))
|
""" % (helpers.verbose or 0, len(content))
|
||||||
pyscript = re.sub(r'\s+', ' ', pyscript.strip())
|
pyscript = re.sub(r'\s+', ' ', pyscript.strip())
|
||||||
@ -135,7 +135,7 @@ def connect(ssh_cmd, rhostport, python, stderr, add_cmd_delimiter, options):
|
|||||||
else:
|
else:
|
||||||
portl = []
|
portl = []
|
||||||
if python:
|
if python:
|
||||||
pycmd = "'%s' -c '%s'" % (python, pyscript)
|
pycmd = '"%s" -c "%s"' % (python, pyscript)
|
||||||
else:
|
else:
|
||||||
# By default, we run the following code in a shell.
|
# By default, we run the following code in a shell.
|
||||||
# However, with restricted shells and other unusual
|
# However, with restricted shells and other unusual
|
||||||
|
@ -168,6 +168,8 @@ class SockWrapper:
|
|||||||
debug3('%r: fixed connect result: %s' % (self, e))
|
debug3('%r: fixed connect result: %s' % (self, e))
|
||||||
if e.args[0] in [errno.EINPROGRESS, errno.EALREADY]:
|
if e.args[0] in [errno.EINPROGRESS, errno.EALREADY]:
|
||||||
pass # not connected yet
|
pass # not connected yet
|
||||||
|
elif sys.platform == 'win32' and e.args[0] == errno.WSAEWOULDBLOCK:
|
||||||
|
pass # not connected yet
|
||||||
elif e.args[0] == 0:
|
elif e.args[0] == 0:
|
||||||
# connected successfully (weird Linux bug?)
|
# connected successfully (weird Linux bug?)
|
||||||
# Sometimes Linux seems to return EINVAL when it isn't
|
# Sometimes Linux seems to return EINVAL when it isn't
|
||||||
@ -382,11 +384,13 @@ class Mux(Handler):
|
|||||||
debug2(' > channel=%d cmd=%s len=%d (fullness=%d)'
|
debug2(' > channel=%d cmd=%s len=%d (fullness=%d)'
|
||||||
% (channel, cmd_to_name.get(cmd, hex(cmd)),
|
% (channel, cmd_to_name.get(cmd, hex(cmd)),
|
||||||
len(data), self.fullness))
|
len(data), self.fullness))
|
||||||
|
# debug3('>>> data: %r' % data)
|
||||||
self.fullness += len(data)
|
self.fullness += len(data)
|
||||||
|
|
||||||
def got_packet(self, channel, cmd, data):
|
def got_packet(self, channel, cmd, data):
|
||||||
debug2('< channel=%d cmd=%s len=%d'
|
debug2('< channel=%d cmd=%s len=%d'
|
||||||
% (channel, cmd_to_name.get(cmd, hex(cmd)), len(data)))
|
% (channel, cmd_to_name.get(cmd, hex(cmd)), len(data)))
|
||||||
|
# debug3('<<< data: %r' % data)
|
||||||
if cmd == CMD_PING:
|
if cmd == CMD_PING:
|
||||||
self.send(0, CMD_PONG, data)
|
self.send(0, CMD_PONG, data)
|
||||||
elif cmd == CMD_PONG:
|
elif cmd == CMD_PONG:
|
||||||
|
Loading…
Reference in New Issue
Block a user