Page Menu
Home
VyOS Platform
Search
Configure Global Search
Log In
Files
F117520806
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
View Options
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
@@ -1,43 +1,54 @@
#!/usr/sbin/nft -f
# 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
{% for r in destination -%}
{% if r.protocol == 'tcp_udp' %}
{# Special handling for protocol tcp_udp which is represented as two individual rules #}
add rule ip nat PREROUTING iifname "{{ r.interface_in }}" tcp dport { {{ r.dest_port }} } counter dnat to {{ r.translation_address }}{{ ":" + r.translation_port if r.translation_port }} comment "DST-NAT-{{ r.number }} tcp_udp"
add rule ip nat PREROUTING iifname "{{ r.interface_in }}" udp dport { {{ r.dest_port }} } counter dnat to {{ r.translation_address }}{{ ":" + r.translation_port if r.translation_port }} comment "DST-NAT-{{ r.number }} tcp_udp"
{% else %}
add rule ip nat PREROUTING iifname "{{ r.interface_in }}" {{ r.protocol }} dport { {{ r.dest_port }} } counter dnat to {{ r.translation_address }}{{ ":" + r.translation_port if r.translation_port }} comment "DST-NAT-{{ r.number }}"
{% endif %}
{% endfor %}
{% for r in source -%}
{% if r.log %}
{% if r.exclude %}
{% set value = 'EXCL' %}
{% elif r.translation_address == 'masquerade' %}
{% set value = 'MASQ' %}
{% endif %}
add rule ip nat POSTROUTING oifname "{{ r.interface_out }}" ip saddr {{ r.source_address }} counter log prefix "[NAT-SRC-{{ r.number }}-{{ value }}]" comment "SRC-NAT-{{ r.number }}"
{% endif %}
{% if r.exclude %}
{% set value = 'return' %}
{% elif r.translation_address == 'masquerade' %}
{% set value = 'masquerade' %}
{% else %}
{% set value = 'snat to ' + r.translation_address %}
{% endif %}
add rule ip nat POSTROUTING oifname "{{ r.interface_out }}" ip saddr {{ r.source_address }} counter {{ value }} comment "SRC-NAT-{{ r.number }}"
{% endfor %}
diff --git a/debian/control b/debian/control
index 2aaca13ba..609f46e4d 100644
--- a/debian/control
+++ b/debian/control
@@ -1,111 +1,111 @@
Source: vyos-1x
Section: contrib/net
Priority: extra
Maintainer: VyOS Package Maintainers <maintainers@vyos.net>
Build-Depends: debhelper (>= 9),
quilt,
python3,
python3-setuptools,
quilt,
python3-lxml,
python3-nose,
python3-coverage,
whois,
fakeroot,
libvyosconfig0 (>= 0.0.7)
Standards-Version: 3.9.6
Package: vyos-1x
Architecture: all
Depends: python3,
${python3:Depends},
python3-netifaces,
python3-jinja2,
python3-pystache,
python3-psutil,
python3-tabulate,
python3-six,
python3-isc-dhcp-leases,
python3-hurry.filesize,
python3-vici (>= 5.7.2),
python3-flask,
python3-waitress,
python3-netaddr,
python3-zmq,
cron,
easy-rsa,
ipaddrcheck,
tcpdump,
tshark,
isc-dhcp-client,
bmon,
hvinfo,
file,
lsscsi,
pciutils,
usbutils,
procps,
snmp, snmpd,
openssh-server,
ntp,
ntpdate,
iputils-arping,
libvyosconfig0,
beep,
isc-dhcp-server,
isc-dhcp-relay,
keepalived (>=2.0.5),
wireguard,
tftpd-hpa,
igmpproxy,
accel-ppp,
mdns-repeater,
udp-broadcast-relay,
pdns-recursor,
lcdproc,
lcdproc-extra-drivers,
openvpn,
openvpn-auth-ldap,
openvpn-auth-radius,
libpam-radius-auth (>= 1.5.0),
mtr-tiny,
telnet,
traceroute,
vyos-qat-kernel-modules,
vyos-qat-utilities,
ssl-cert,
nginx-light,
lldpd,
iperf,
iperf3,
frr,
radvd,
dbus,
usb-modeswitch,
hostapd (>= 0.6.8),
wpasupplicant (>= 0.6.7),
iw,
crda,
wireless-regdb,
pmacct (>= 1.6.0),
python3-certbot-nginx,
pppoe,
salt-minion,
vyos-utils,
- nftables,
+ nftables (>= 0.9.3),
conntrack,
${shlibs:Depends},
${misc:Depends}
Description: VyOS configuration scripts and data
VyOS configuration scripts, interface definitions, and everything
Package: vyos-1x-vmware
Architecture: amd64 i386
Depends:
${misc:Depends},
${shlibs:Depends},
vyos-1x,
open-vm-tools
Description: VyOS configuration scripts and data for VMware
Adds configuration files required for VyOS running on VMware hosts.
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
@@ -1,159 +1,198 @@
#!/usr/bin/env python3
#
# Copyright (C) 2020 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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
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 = []
base_level = ['nat', source_dest]
conf.set_level(base_level)
for number in conf.list_nodes(['rule']):
rule = {
'description': '',
'dest_address': '',
'dest_port': '',
'disable': False,
'exclude': False,
'interface_in': '',
'interface_out': '',
'log': False,
'protocol': '',
'number': number,
'source_address': '',
'source_port': '',
'translation_address': '',
'translation_port': ''
}
conf.set_level(base_level + ['rule', number])
if conf.exists(['description']):
rule['description'] = conf.return_value(['description'])
if conf.exists(['destination', 'address']):
rule['dest_address'] = conf.return_value(['destination', 'address'])
if conf.exists(['destination', 'port']):
rule['dest_port'] = conf.return_value(['destination', 'port'])
if conf.exists(['disable']):
rule['disable'] = True
if conf.exists(['exclude']):
rule['exclude'] = True
if conf.exists(['inbound-interface']):
rule['interface_in'] = conf.return_value(['inbound-interface'])
if conf.exists(['outbound-interface']):
rule['interface_out'] = conf.return_value(['outbound-interface'])
if conf.exists(['log']):
rule['log'] = True
if conf.exists(['protocol']):
rule['protocol'] = conf.return_value(['protocol'])
if conf.exists(['source', 'address']):
rule['source_address'] = conf.return_value(['source', 'address'])
if conf.exists(['source', 'port']):
rule['source_port'] = conf.return_value(['source', 'port'])
if conf.exists(['translation', 'address']):
rule['translation_address'] = conf.return_value(['translation', 'address'])
if conf.exists(['translation', 'port']):
rule['translation_port'] = conf.return_value(['translation', 'port'])
tmp.append(rule)
return tmp
def get_config():
nat = deepcopy(default_config_data)
conf = Config()
if not conf.exists(['nat']):
return None
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 :-)
for tgt in ['source', 'destination']:
nat[tgt] = parse_source_destination(conf, tgt)
return nat
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():
print(f'NAT configuration warning: interface {interface} does not exist on this system')
return None
def generate(nat):
if not nat:
return None
render(iptables_nat_config, 'firewall/nftables-nat.tmpl', nat, trim_blocks=True, permission=0o755)
+
return None
def apply(nat):
if not nat:
return None
call(f'{iptables_nat_config}')
return None
if __name__ == '__main__':
try:
_check_kmod()
c = get_config()
verify(c)
generate(c)
apply(c)
except ConfigError as e:
print(e)
exit(1)
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Sep 26, 12:23 PM (1 d, 22 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4285128
Default Alt Text
(11 KB)
Attached To
Mode
rVYOSONEX vyos-1x
Attached
Detach File
Event Timeline
Log In to Comment