mirror of
https://github.com/sshuttle/sshuttle.git
synced 2025-01-03 20:49:02 +01:00
Add support for iproute2
`netstat` has been deprecated for some time and some distros might start shipping without it in the near future. This commit adds support for `ip route` and uses it when available.
This commit is contained in:
parent
abce18cfc2
commit
809fad537f
@ -15,6 +15,11 @@ from sshuttle.ssnet import Handler, Proxy, Mux, MuxWrapper
|
||||
from sshuttle.helpers import b, log, debug1, debug2, debug3, Fatal, \
|
||||
resolvconf_random_nameserver
|
||||
|
||||
try:
|
||||
from shutil import which
|
||||
except ImportError:
|
||||
from distutils.spawn import find_executable as which
|
||||
|
||||
|
||||
def _ipmatch(ipstr):
|
||||
# FIXME: IPv4 only
|
||||
@ -60,9 +65,29 @@ def _shl(n, bits):
|
||||
return n * int(2 ** bits)
|
||||
|
||||
|
||||
def _list_routes():
|
||||
def _route_netstat(line):
|
||||
cols = re.split(r'\s+', line.decode("ASCII"))
|
||||
ipw = _ipmatch(cols[0])
|
||||
if not ipw:
|
||||
return None, None # some lines won't be parseable; never mind
|
||||
maskw = _ipmatch(cols[2]) # linux only
|
||||
mask = _maskbits(maskw) # returns 32 if maskw is null
|
||||
return ipw, mask
|
||||
|
||||
|
||||
def _route_iproute(line):
|
||||
ipm = line.decode("ASCII").split(None, 1)[0]
|
||||
if ipm == 'default':
|
||||
return None, None
|
||||
ip, mask = ipm.split('/')
|
||||
ipw = _ipmatch(ip)
|
||||
if not ipw:
|
||||
return None, None # some lines won't be parseable; never mind
|
||||
return ipw, int(mask)
|
||||
|
||||
|
||||
def _list_routes(argv, extract_route):
|
||||
# FIXME: IPv4 only
|
||||
argv = ['netstat', '-rn']
|
||||
env = {
|
||||
'PATH': os.environ['PATH'],
|
||||
'LC_ALL': "C",
|
||||
@ -70,12 +95,9 @@ def _list_routes():
|
||||
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, env=env)
|
||||
routes = []
|
||||
for line in p.stdout:
|
||||
cols = re.split(r'\s+', line.decode("ASCII"))
|
||||
ipw = _ipmatch(cols[0])
|
||||
ipw, mask = extract_route(line)
|
||||
if not ipw:
|
||||
continue # some lines won't be parseable; never mind
|
||||
maskw = _ipmatch(cols[2]) # linux only
|
||||
mask = _maskbits(maskw) # returns 32 if maskw is null
|
||||
continue
|
||||
width = min(ipw[1], mask)
|
||||
ip = ipw[0] & _shl(_shl(1, width) - 1, 32 - width)
|
||||
routes.append(
|
||||
@ -84,11 +106,20 @@ def _list_routes():
|
||||
if rv != 0:
|
||||
log('WARNING: %r returned %d\n' % (argv, rv))
|
||||
log('WARNING: That prevents --auto-nets from working.\n')
|
||||
|
||||
return routes
|
||||
|
||||
|
||||
def list_routes():
|
||||
for (family, ip, width) in _list_routes():
|
||||
if which('ip'):
|
||||
routes = _list_routes(['ip', 'route'], _route_iproute)
|
||||
elif which('netstat'):
|
||||
routes = _list_routes(['netstat', '-rn'], _route_netstat)
|
||||
else:
|
||||
log('WARNING: Neither ip nor netstat were found on the server.\n')
|
||||
routes = []
|
||||
|
||||
for (family, ip, width) in routes:
|
||||
if not ip.startswith('0.') and not ip.startswith('127.'):
|
||||
yield (family, ip, width)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user