Commit 3edeb726 authored by Julian Wollrath's avatar Julian Wollrath Committed by Brian May

Simplify nftables based method

parent 6e9c58b4
......@@ -44,7 +44,7 @@ Options
to during startup will be routed over the VPN. Valid examples are
example.com, example.com:8000 and example.com:8000-9000.
.. option:: --method [auto|nat|tproxy|pf]
.. option:: --method [auto|nat|nft|tproxy|pf]
Which firewall method should sshuttle use? For auto, sshuttle attempts to
guess the appropriate method depending on what it can find in PATH. The
......
import re
import os
import socket
import subprocess as ssubprocess
from sshuttle.helpers import log, debug1, Fatal, family_to_string
......@@ -52,10 +50,8 @@ def ipt(family, table, *args):
def nft(family, table, action, *args):
if family == socket.AF_INET:
argv = ['nft', action, 'ip', table] + list(args)
elif family == socket.AF_INET6:
argv = ['nft', action, 'ip6', table] + list(args)
if family in (socket.AF_INET, socket.AF_INET6):
argv = ['nft', action, 'inet', table] + list(args)
else:
raise Exception('Unsupported family "%s"' % family_to_string(family))
debug1('>> %s\n' % ' '.join(argv))
......@@ -68,48 +64,6 @@ def nft(family, table, action, *args):
raise Fatal('%r returned %d' % (argv, rv))
def nft_chain_exists(family, table, name):
if family == socket.AF_INET:
fam = 'ip'
elif family == socket.AF_INET6:
fam = 'ip6'
else:
raise Exception('Unsupported family "%s"' % family_to_string(family))
argv = ['nft', 'list', 'chain', fam, table, name]
debug1('>> %s\n' % ' '.join(argv))
env = {
'PATH': os.environ['PATH'],
'LC_ALL': "C",
}
try:
table_exists = False
output = ssubprocess.check_output(argv, env=env,
stderr=ssubprocess.STDOUT)
for line in output.decode('ASCII').split('\n'):
if line.startswith('table %s %s ' % (fam, table)):
table_exists = True
if table_exists and ('chain %s {' % name) in line:
return True
except ssubprocess.CalledProcessError:
return False
def nft_get_handle(expression, chain):
cmd = 'nft'
argv = [cmd, 'list', expression, '-a']
env = {
'PATH': os.environ['PATH'],
'LC_ALL': "C",
}
try:
output = ssubprocess.check_output(argv, env=env)
for line in output.decode('utf-8').split('\n'):
if ('jump %s' % chain) in line:
return re.sub('.*# ', '', line)
except ssubprocess.CalledProcessError as e:
raise Fatal('%r returned %d' % (argv, e.returncode))
_no_ttl_module = False
......
import socket
from sshuttle.firewall import subnet_weight
from sshuttle.linux import nft, nft_get_handle, nft_chain_exists, nonfatal
from sshuttle.linux import nft, nonfatal
from sshuttle.methods import BaseMethod
......@@ -16,22 +16,19 @@ class Method(BaseMethod):
if udp:
raise Exception("UDP not supported by nft")
table = "nat"
table = 'sshuttle-%s' % port
def _nft(action, *args):
return nft(family, table, action, *args)
chain = table
# basic cleanup/setup of chains
_nft('add table', '')
# prerouting, postrouting, and output chains may already exist
for chain in ['prerouting', 'postrouting', 'output']:
rules = '{{ type nat hook {} priority -100; policy accept; }}' \
.format(chain)
if not nft_chain_exists(family, table, chain):
_nft('add chain', chain, rules)
chain = 'sshuttle-%s' % port
_nft('add chain', 'prerouting',
'{ type nat hook prerouting priority -100; policy accept; }')
_nft('add chain', 'output',
'{ type nat hook output priority -100; policy accept; }')
_nft('add chain', chain)
_nft('flush chain', chain)
_nft('add rule', 'output jump %s' % chain)
......@@ -70,16 +67,10 @@ class Method(BaseMethod):
if udp:
raise Exception("UDP not supported by nft method_name")
table = "nat"
table = 'sshuttle-%s' % port
def _nft(action, *args):
return nft(family, table, action, *args)
chain = 'sshuttle-%s' % port
# basic cleanup/setup of chains
handle = nft_get_handle('chain ip nat output', chain)
nonfatal(_nft, 'delete rule', 'output', handle)
handle = nft_get_handle('chain ip nat prerouting', chain)
nonfatal(_nft, 'delete rule', 'prerouting', handle)
nonfatal(_nft, 'delete chain', chain)
nonfatal(_nft, 'delete table', '')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment