From a821b8c603999665ce8a77acb0e44a743811992a Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Mon, 22 Jan 2024 20:05:15 +0100 Subject: vrf: T5973: ensure Kernel module is loaded This prevents the following error when configuring the first VRF: sysctl: cannot stat /proc/sys/net/vrf/strict_mode: No such file or directory --- src/conf_mode/vrf.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/conf_mode') diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py index 9b1b6355f..aac9b0616 100755 --- a/src/conf_mode/vrf.py +++ b/src/conf_mode/vrf.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2023 VyOS maintainers and contributors +# Copyright (C) 2020-2024 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 @@ -27,6 +27,7 @@ from vyos.ifconfig import Interface from vyos.template import render from vyos.template import render_to_string from vyos.utils.dict import dict_search +from vyos.utils.kernel import check_kmod from vyos.utils.network import get_interface_config from vyos.utils.network import get_vrf_members from vyos.utils.network import interface_exists @@ -43,6 +44,8 @@ airbag.enable() config_file = '/etc/iproute2/rt_tables.d/vyos-vrf.conf' nft_vrf_config = '/tmp/nftables-vrf-zones' +k_mod = ['vrf'] + def has_rule(af : str, priority : int, table : str): """ Check if a given ip rule exists """ if af not in ['-4', '-6']: @@ -329,6 +332,7 @@ def apply(vrf): if __name__ == '__main__': try: + check_kmod(k_mod) c = get_config() verify(c) generate(c) -- cgit v1.2.3 From 89f0d347bfe5e468355817a617dc71823a58c284 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Mon, 22 Jan 2024 20:48:44 +0100 Subject: vrf: T5973: move initial conntrack firewall table to startup There is no need to add and remove this table during runtime - it can lurk in the standard firewall init code. --- data/templates/firewall/nftables-vrf-zones.j2 | 17 ----------------- data/vyos-firewall-init.conf | 19 +++++++++++++++++++ src/conf_mode/vrf.py | 21 --------------------- 3 files changed, 19 insertions(+), 38 deletions(-) delete mode 100644 data/templates/firewall/nftables-vrf-zones.j2 (limited to 'src/conf_mode') diff --git a/data/templates/firewall/nftables-vrf-zones.j2 b/data/templates/firewall/nftables-vrf-zones.j2 deleted file mode 100644 index 3bce7312d..000000000 --- a/data/templates/firewall/nftables-vrf-zones.j2 +++ /dev/null @@ -1,17 +0,0 @@ -table inet vrf_zones { - # Map of interfaces and connections tracking zones - map ct_iface_map { - typeof iifname : ct zone - } - # Assign unique zones for each VRF - # Chain for inbound traffic - chain vrf_zones_ct_in { - type filter hook prerouting priority raw; policy accept; - counter ct original zone set iifname map @ct_iface_map - } - # Chain for locally-generated traffic - chain vrf_zones_ct_out { - type filter hook output priority raw; policy accept; - counter ct original zone set oifname map @ct_iface_map - } -} diff --git a/data/vyos-firewall-init.conf b/data/vyos-firewall-init.conf index cd7d5011f..5a4e03015 100644 --- a/data/vyos-firewall-init.conf +++ b/data/vyos-firewall-init.conf @@ -54,3 +54,22 @@ table ip6 raw { type filter hook prerouting priority -300; policy accept; } } + +# Required by VRF +table inet vrf_zones { + # Map of interfaces and connections tracking zones + map ct_iface_map { + typeof iifname : ct zone + } + # Assign unique zones for each VRF + # Chain for inbound traffic + chain vrf_zones_ct_in { + type filter hook prerouting priority raw; policy accept; + counter ct original zone set iifname map @ct_iface_map + } + # Chain for locally-generated traffic + chain vrf_zones_ct_out { + type filter hook output priority raw; policy accept; + counter ct original zone set oifname map @ct_iface_map + } +} diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py index aac9b0616..1db4e99f2 100755 --- a/src/conf_mode/vrf.py +++ b/src/conf_mode/vrf.py @@ -33,8 +33,6 @@ from vyos.utils.network import get_vrf_members from vyos.utils.network import interface_exists from vyos.utils.process import call from vyos.utils.process import cmd -from vyos.utils.process import popen -from vyos.utils.process import run from vyos.utils.system import sysctl_write from vyos import ConfigError from vyos import frr @@ -42,8 +40,6 @@ from vyos import airbag airbag.enable() config_file = '/etc/iproute2/rt_tables.d/vyos-vrf.conf' -nft_vrf_config = '/tmp/nftables-vrf-zones' - k_mod = ['vrf'] def has_rule(af : str, priority : int, table : str): @@ -176,8 +172,6 @@ def verify(vrf): def generate(vrf): # Render iproute2 VR helper names render(config_file, 'iproute2/vrf.conf.j2', vrf) - # Render nftables zones config - render(nft_vrf_config, 'firewall/nftables-vrf-zones.j2', vrf) # Render VRF Kernel/Zebra route-map filters vrf['frr_zebra_config'] = render_to_string('frr/zebra.vrf.route-map.frr.j2', vrf) @@ -230,14 +224,6 @@ def apply(vrf): sysctl_write('net.vrf.strict_mode', strict_mode) if 'name' in vrf: - # Separate VRFs in conntrack table - # check if table already exists - _, err = popen('nft list table inet vrf_zones') - # If not, create a table - if err and os.path.exists(nft_vrf_config): - cmd(f'nft -f {nft_vrf_config}') - os.unlink(nft_vrf_config) - # Linux routing uses rules to find tables - routing targets are then # looked up in those tables. If the lookup got a matching route, the # process ends. @@ -321,13 +307,6 @@ def apply(vrf): frr_cfg.add_before(frr.default_add_before, vrf['frr_zebra_config']) frr_cfg.commit_configuration(zebra_daemon) - # return to default lookup preference when no VRF is configured - if 'name' not in vrf: - # Remove VRF zones table from nftables - tmp = run('nft list table inet vrf_zones') - if tmp == 0: - cmd('nft delete table inet vrf_zones') - return None if __name__ == '__main__': -- cgit v1.2.3 From a009143a62caca207fdffffcf0b490c747a87025 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Mon, 22 Jan 2024 20:49:35 +0100 Subject: vrf: T5973: fix has_rule() to check for l3mdev rule A code path was missing to check if only priority is available in the result of "ip --json -4 rule show", in the case of l3mdev it's a dedicated key! --- src/conf_mode/vrf.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src/conf_mode') diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py index 1db4e99f2..f2c544aa6 100755 --- a/src/conf_mode/vrf.py +++ b/src/conf_mode/vrf.py @@ -42,15 +42,27 @@ airbag.enable() config_file = '/etc/iproute2/rt_tables.d/vyos-vrf.conf' k_mod = ['vrf'] -def has_rule(af : str, priority : int, table : str): - """ Check if a given ip rule exists """ +def has_rule(af : str, priority : int, table : str=None): + """ + Check if a given ip rule exists + $ ip --json -4 rule show + [{'l3mdev': None, 'priority': 1000, 'src': 'all'}, + {'action': 'unreachable', 'l3mdev': None, 'priority': 2000, 'src': 'all'}, + {'priority': 32765, 'src': 'all', 'table': 'local'}, + {'priority': 32766, 'src': 'all', 'table': 'main'}, + {'priority': 32767, 'src': 'all', 'table': 'default'}] + """ if af not in ['-4', '-6']: raise ValueError() - command = f'ip -j {af} rule show' + command = f'ip --detail --json {af} rule show' for tmp in loads(cmd(command)): - if {'priority', 'table'} <= set(tmp): + if 'priority' in tmp and 'table' in tmp: if tmp['priority'] == priority and tmp['table'] == table: return True + elif 'priority' in tmp and table in tmp: + # l3mdev table has a different layout + if tmp['priority'] == priority: + return True return False def vrf_interfaces(c, match): -- cgit v1.2.3