mirror of
https://github.com/sshuttle/sshuttle.git
synced 2025-01-05 21:48:54 +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, \
|
from sshuttle.helpers import b, log, debug1, debug2, debug3, Fatal, \
|
||||||
resolvconf_random_nameserver
|
resolvconf_random_nameserver
|
||||||
|
|
||||||
|
try:
|
||||||
|
from shutil import which
|
||||||
|
except ImportError:
|
||||||
|
from distutils.spawn import find_executable as which
|
||||||
|
|
||||||
|
|
||||||
def _ipmatch(ipstr):
|
def _ipmatch(ipstr):
|
||||||
# FIXME: IPv4 only
|
# FIXME: IPv4 only
|
||||||
@ -60,9 +65,29 @@ def _shl(n, bits):
|
|||||||
return n * int(2 ** 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
|
# FIXME: IPv4 only
|
||||||
argv = ['netstat', '-rn']
|
|
||||||
env = {
|
env = {
|
||||||
'PATH': os.environ['PATH'],
|
'PATH': os.environ['PATH'],
|
||||||
'LC_ALL': "C",
|
'LC_ALL': "C",
|
||||||
@ -70,12 +95,9 @@ def _list_routes():
|
|||||||
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, env=env)
|
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, env=env)
|
||||||
routes = []
|
routes = []
|
||||||
for line in p.stdout:
|
for line in p.stdout:
|
||||||
cols = re.split(r'\s+', line.decode("ASCII"))
|
ipw, mask = extract_route(line)
|
||||||
ipw = _ipmatch(cols[0])
|
|
||||||
if not ipw:
|
if not ipw:
|
||||||
continue # some lines won't be parseable; never mind
|
continue
|
||||||
maskw = _ipmatch(cols[2]) # linux only
|
|
||||||
mask = _maskbits(maskw) # returns 32 if maskw is null
|
|
||||||
width = min(ipw[1], mask)
|
width = min(ipw[1], mask)
|
||||||
ip = ipw[0] & _shl(_shl(1, width) - 1, 32 - width)
|
ip = ipw[0] & _shl(_shl(1, width) - 1, 32 - width)
|
||||||
routes.append(
|
routes.append(
|
||||||
@ -84,11 +106,20 @@ def _list_routes():
|
|||||||
if rv != 0:
|
if rv != 0:
|
||||||
log('WARNING: %r returned %d\n' % (argv, rv))
|
log('WARNING: %r returned %d\n' % (argv, rv))
|
||||||
log('WARNING: That prevents --auto-nets from working.\n')
|
log('WARNING: That prevents --auto-nets from working.\n')
|
||||||
|
|
||||||
return routes
|
return routes
|
||||||
|
|
||||||
|
|
||||||
def list_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.'):
|
if not ip.startswith('0.') and not ip.startswith('127.'):
|
||||||
yield (family, ip, width)
|
yield (family, ip, width)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user