diff options
| author | Nataliia Solomko <natalirs1985@gmail.com> | 2026-05-07 12:18:47 +0300 |
|---|---|---|
| committer | Nataliia Solomko <natalirs1985@gmail.com> | 2026-05-11 14:07:58 +0300 |
| commit | fea16e41f9a3f4aef4251786b7d157e781368cb9 (patch) | |
| tree | d51dd39cd0e33f087ac9be2731973931e200eea4 /src | |
| parent | 7cf4d14610a021d13e1a54df05cf1bffc03f714b (diff) | |
| download | vyos-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-x | src/conf_mode/interfaces_wireguard.py | 34 | ||||
| -rwxr-xr-x | src/conf_mode/vrf.py | 6 |
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}') |
