summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNataliia Solomko <natalirs1985@gmail.com>2026-05-07 12:18:47 +0300
committerNataliia Solomko <natalirs1985@gmail.com>2026-05-11 14:07:58 +0300
commitfea16e41f9a3f4aef4251786b7d157e781368cb9 (patch)
treed51dd39cd0e33f087ac9be2731973931e200eea4 /src
parent7cf4d14610a021d13e1a54df05cf1bffc03f714b (diff)
downloadvyos-1x-fea16e41f9a3f4aef4251786b7d157e781368cb9.tar.gz
vyos-1x-fea16e41f9a3f4aef4251786b7d157e781368cb9.zip
wireguard: T8509: Add fwmark ip rules for VRF-bound interfaces
When a WireGuard interface has both fwmark and VRF configured, outgoing tunnel packets marked with the fwmark were not routed into the correct VRF routing table, causing them to hit the l3mdev unreachable rule instead. Add an ip rule at priority 1998 (after l3mdev at 1000 and before l3mdev unreachable at 2000) to route fwmark-tagged packets into the correct VRF routing table.
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/interfaces_wireguard.py34
-rwxr-xr-xsrc/conf_mode/vrf.py6
2 files changed, 40 insertions, 0 deletions
diff --git a/src/conf_mode/interfaces_wireguard.py b/src/conf_mode/interfaces_wireguard.py
index b430fa94a..92e3a239d 100755
--- a/src/conf_mode/interfaces_wireguard.py
+++ b/src/conf_mode/interfaces_wireguard.py
@@ -34,6 +34,7 @@ from vyos.configverify import verify_bond_bridge_member
from vyos.ifconfig import WireGuardIf
from vyos.utils.kernel import check_kmod
from vyos.utils.network import check_port_availability
+from vyos.utils.network import get_vrf_tableid
from vyos.utils.network import is_wireguard_key_pair
from vyos.utils.process import call
from vyos import ConfigError
@@ -75,6 +76,16 @@ def get_config(config=None):
else:
wireguard['is_source_interface'] = tmp
+ if is_node_changed(conf, base + [ifname, 'fwmark']) or is_node_changed(
+ conf, base + [ifname, 'vrf']
+ ):
+ wireguard['fwmark_vrf_changed'] = {}
+ prev = conf.get_config_dict(
+ base + [ifname], effective=True, key_mangling=('-', '_'), get_first_key=True
+ )
+ wireguard['prev_fwmark'] = prev.get('fwmark')
+ wireguard['prev_vrf'] = prev.get('vrf')
+
return wireguard
@@ -154,6 +165,29 @@ def apply(wireguard):
else:
wg.update(wireguard)
+ # delete old fwmark-based ip rule if fwmark or VRF was changed
+ if 'fwmark_vrf_changed' in wireguard or 'deleted' in wireguard:
+ prev_fwmark = wireguard.get('prev_fwmark')
+ prev_vrf = wireguard.get('prev_vrf')
+ if prev_fwmark is not None and prev_vrf is not None:
+ table_id = get_vrf_tableid(prev_vrf)
+ if table_id is not None:
+ for afi in ['-4', '-6']:
+ call(
+ f'ip {afi} rule del pref 1998 fwmark {prev_fwmark} table {table_id}'
+ )
+
+ # Add ip rule to route fwmark-marked WireGuard tunnel packets into the
+ # correct VRF routing table. This is required for VRF-bound WireGuard
+ # interfaces with fwmark set, so that outgoing encapsulated packets use the
+ # proper VRF routes (otherwise, they may be unroutable or use the main table).
+ if wireguard.get('fwmark', '0') != '0' and 'vrf' in wireguard:
+ table_id = get_vrf_tableid(wireguard['vrf'])
+ for afi in ['-4', '-6']:
+ call(
+ f'ip {afi} rule add pref 1998 fwmark {wireguard["fwmark"]} table {table_id}'
+ )
+
domain_resolver_usage = '/run/use-vyos-domain-resolver-interfaces-wireguard-' + wireguard['ifname']
## DOMAIN RESOLVER
diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py
index 92bb956ed..c307ae27e 100755
--- a/src/conf_mode/vrf.py
+++ b/src/conf_mode/vrf.py
@@ -265,6 +265,12 @@ def apply(vrf):
# Remove map element
cmd(f'nft {nft_del_element}')
+ # Remove all ip rules pointing to this VRF table
+ table_id = get_vrf_tableid(tmp)
+ for afi in ['-4', '-6']:
+ while call(f'ip {afi} rule del table {table_id}') == 0:
+ pass
+
# Delete the VRF Kernel interface
call(f'ip link delete dev {tmp}')