summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/firewall/nftables-nat.tmpl19
-rw-r--r--debian/control2
-rwxr-xr-xsrc/conf_mode/nat.py45
3 files changed, 58 insertions, 8 deletions
diff --git a/data/templates/firewall/nftables-nat.tmpl b/data/templates/firewall/nftables-nat.tmpl
index 340ab3678..343807e79 100644
--- a/data/templates/firewall/nftables-nat.tmpl
+++ b/data/templates/firewall/nftables-nat.tmpl
@@ -3,11 +3,22 @@
# Start with a "clean" NAT table
flush table nat
+{% for rule in init_deinit -%}
+# Add or remove conntrack helper rules for NAT operation-
+{{ rule }}
+{% endfor %}
+
add chain ip raw NAT_CONNTRACK
-add rule ip raw PREROUTING position 25 counter jump VYATTA_CT_HELPER
-add rule ip raw PREROUTING position 17 counter jump NAT_CONNTRACK
-add rule ip raw OUTPUT position 26 counter jump VYATTA_CT_HELPER
-add rule ip raw OUTPUT position 21 counter jump NAT_CONNTRACK
+
+# insert rule after VYATTA_CT_IGNORE
+add rule ip raw PREROUTING position {{ pre_ct_ignore }} counter jump VYATTA_CT_HELPER
+# insert rule after VYATTA_CT_PREROUTING_HOOK
+add rule ip raw PREROUTING position {{ pre_ct_conntrack }} counter jump NAT_CONNTRACK
+# insert rule after VYATTA_CT_IGNORE
+add rule ip raw OUTPUT position {{ out_ct_ignore }} counter jump VYATTA_CT_HELPER
+# insert rule after VYATTA_CT_PREROUTING_HOOK
+add rule ip raw OUTPUT position {{ out_ct_conntrack }} counter jump NAT_CONNTRACK
+
add rule ip raw NAT_CONNTRACK counter accept
diff --git a/debian/control b/debian/control
index 2aaca13ba..609f46e4d 100644
--- a/debian/control
+++ b/debian/control
@@ -92,7 +92,7 @@ Depends: python3,
pppoe,
salt-minion,
vyos-utils,
- nftables,
+ nftables (>= 0.9.3),
conntrack,
${shlibs:Depends},
${misc:Depends}
diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py
index 2e866fdf4..128e2469c 100755
--- a/src/conf_mode/nat.py
+++ b/src/conf_mode/nat.py
@@ -14,6 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import json
import os
from copy import deepcopy
@@ -21,24 +22,53 @@ from sys import exit
from netifaces import interfaces
from vyos.config import Config
-from vyos.util import call
from vyos.template import render
+from vyos.util import call, cmd
from vyos import ConfigError
default_config_data = {
- 'source': [],
- 'destination': []
+ 'prerouting_ct_helper': '',
+ 'prerouting_ct_conntrack': '',
+ 'output_ct_helper': '',
+ 'output_ct_conntrack': '',
+ 'destination': [],
+ 'source': []
}
iptables_nat_config = '/tmp/vyos-nat-rules.nft'
def _check_kmod():
+ """ load required Kernel modules """
modules = ['nft_nat', 'nft_chain_nat_ipv4']
for module in modules:
if not os.path.exists(f'/sys/module/{module}'):
if call(f'modprobe {module}') != 0:
raise ConfigError(f'Loading Kernel module {module} failed')
+
+def get_handler(chain, target):
+ """ Get handler number of given chain/target combination. Handler is
+ required when adding NAT/Conntrack helper targets """
+ tmp = json.loads(cmd('nft -j list table raw'))
+ for rule in tmp.get('nftables'):
+ # We're only interested in rules - not chains
+ if not 'rule' in rule.keys():
+ continue
+
+ # Search for chain of interest
+ if rule['rule']['chain'] == chain:
+ for expr in rule['rule']['expr']:
+ # We're only interested in jump targets
+ if not 'jump' in expr.keys():
+ continue
+
+ # Search for target of interest
+ if expr['jump']['target'] == target:
+ return rule['rule']['handle']
+
+ return None
+
+
def parse_source_destination(conf, source_dest):
""" Common wrapper to read in both NAT source and destination CLI """
tmp = []
@@ -114,6 +144,11 @@ def get_config():
else:
conf.set_level(['nat'])
+ nat['pre_ct_ignore'] = get_handler('PREROUTING', 'VYATTA_CT_IGNORE')
+ nat['pre_ct_conntrack'] = get_handler('PREROUTING', 'VYATTA_CT_PREROUTING_HOOK')
+ nat['out_ct_ignore'] = get_handler('OUTPUT', 'VYATTA_CT_IGNORE')
+ nat['out_ct_conntrack'] = get_handler('OUTPUT', 'VYATTA_CT_OUTPUT_HOOK')
+
# use a common wrapper function to read in the source / destination
# tree from the config - thus we do not need to replicate almost the
# same code :-)
@@ -126,6 +161,9 @@ def verify(nat):
if not nat:
return None
+ if not (nat['pre_ct_ignore'] or nat['pre_ct_conntrack'] or nat['out_ct_ignore'] or nat['out_ct_conntrack']):
+ raise Exception('could not determine nftable ruleset handlers')
+
for rule in nat['source']:
interface = rule['interface_out']
if interface and interface not in interfaces():
@@ -138,6 +176,7 @@ def generate(nat):
return None
render(iptables_nat_config, 'firewall/nftables-nat.tmpl', nat, trim_blocks=True, permission=0o755)
+
return None
def apply(nat):