diff options
| author | Christian Breunig <christian@breunig.cc> | 2026-01-05 16:12:50 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-05 16:12:50 +0100 |
| commit | 0da5b3c18ef56ab13cabbbf874f41e8c5b35a518 (patch) | |
| tree | 35ec3a0d999f977718b26ec5e6507b935148c7e0 | |
| parent | 1fc20e61560d26abec5277a62a318070c8596437 (diff) | |
| parent | 95f40d8b30f03a47b022042ed8b3c179b0e7abdf (diff) | |
| download | vyos-1x-0da5b3c18ef56ab13cabbbf874f41e8c5b35a518.tar.gz vyos-1x-0da5b3c18ef56ab13cabbbf874f41e8c5b35a518.zip | |
Merge pull request #4928 from bilde2910/T8139
nat66: T8139: add support for NAT66 source groups
| -rw-r--r-- | interface-definitions/nat66.xml.in | 2 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_nat66.py | 18 | ||||
| -rwxr-xr-x | src/conf_mode/nat66.py | 14 |
3 files changed, 29 insertions, 5 deletions
diff --git a/interface-definitions/nat66.xml.in b/interface-definitions/nat66.xml.in index 2c1babd5a..3848b4c9a 100644 --- a/interface-definitions/nat66.xml.in +++ b/interface-definitions/nat66.xml.in @@ -79,6 +79,7 @@ </properties> </leafNode> #include <include/nat-port.xml.i> + #include <include/firewall/source-destination-group-ipv6.xml.i> </children> </node> <node name="translation"> @@ -216,6 +217,7 @@ </properties> </leafNode> #include <include/nat-port.xml.i> + #include <include/firewall/source-destination-group-ipv6.xml.i> </children> </node> <node name="translation"> diff --git a/smoketest/scripts/cli/test_nat66.py b/smoketest/scripts/cli/test_nat66.py index 403c428cf..8bec2f998 100755 --- a/smoketest/scripts/cli/test_nat66.py +++ b/smoketest/scripts/cli/test_nat66.py @@ -174,10 +174,13 @@ class TestNAT66(VyOSUnitTestSHIM.TestCase): address_group_member = 'fc00::1' network_group = 'smoketest_net' network_group_member = 'fc00::/64' + mac_group = 'smoketest_mac' + mac_group_member = '00:01:02:03:04:05' translation_prefix = 'fc01::/64' self.cli_set(['firewall', 'group', 'ipv6-address-group', address_group, 'address', address_group_member]) self.cli_set(['firewall', 'group', 'ipv6-network-group', network_group, 'network', network_group_member]) + self.cli_set(['firewall', 'group', 'mac-group', mac_group, 'mac-address', mac_group_member]) self.cli_set(dst_path + ['rule', '1', 'destination', 'group', 'address-group', address_group]) self.cli_set(dst_path + ['rule', '1', 'translation', 'address', translation_prefix]) @@ -185,6 +188,9 @@ class TestNAT66(VyOSUnitTestSHIM.TestCase): self.cli_set(dst_path + ['rule', '2', 'destination', 'group', 'network-group', network_group]) self.cli_set(dst_path + ['rule', '2', 'translation', 'address', translation_prefix]) + self.cli_set(dst_path + ['rule', '3', 'source', 'group', 'mac-group', mac_group]) + self.cli_set(dst_path + ['rule', '3', 'translation', 'address', translation_prefix]) + self.cli_commit() nftables_search = [ @@ -193,7 +199,8 @@ class TestNAT66(VyOSUnitTestSHIM.TestCase): [f'set N6_{network_group}'], [f'elements = {{ {network_group_member} }}'], ['ip6 daddr', f'@A6_{address_group}', 'dnat prefix to fc01::/64'], - ['ip6 daddr', f'@N6_{network_group}', 'dnat prefix to fc01::/64'] + ['ip6 daddr', f'@N6_{network_group}', 'dnat prefix to fc01::/64'], + ['ether saddr', f'@M_{mac_group}', 'dnat prefix to fc01::/64'], ] self.verify_nftables(nftables_search, 'ip6 vyos_nat') @@ -260,10 +267,13 @@ class TestNAT66(VyOSUnitTestSHIM.TestCase): address_group_member = 'fc00::1' network_group = 'smoketest_net' network_group_member = 'fc00::/64' + mac_group = 'smoketest_mac' + mac_group_member = '00:01:02:03:04:05' translation_prefix = 'fc01::/64' self.cli_set(['firewall', 'group', 'ipv6-address-group', address_group, 'address', address_group_member]) self.cli_set(['firewall', 'group', 'ipv6-network-group', network_group, 'network', network_group_member]) + self.cli_set(['firewall', 'group', 'mac-group', mac_group, 'mac-address', mac_group_member]) self.cli_set(src_path + ['rule', '1', 'destination', 'group', 'address-group', address_group]) self.cli_set(src_path + ['rule', '1', 'translation', 'address', translation_prefix]) @@ -271,6 +281,9 @@ class TestNAT66(VyOSUnitTestSHIM.TestCase): self.cli_set(src_path + ['rule', '2', 'destination', 'group', 'network-group', network_group]) self.cli_set(src_path + ['rule', '2', 'translation', 'address', translation_prefix]) + self.cli_set(src_path + ['rule', '3', 'source', 'group', 'mac-group', mac_group]) + self.cli_set(src_path + ['rule', '3', 'translation', 'address', translation_prefix]) + self.cli_commit() nftables_search = [ @@ -279,7 +292,8 @@ class TestNAT66(VyOSUnitTestSHIM.TestCase): [f'set N6_{network_group}'], [f'elements = {{ {network_group_member} }}'], ['ip6 daddr', f'@A6_{address_group}', 'snat prefix to fc01::/64'], - ['ip6 daddr', f'@N6_{network_group}', 'snat prefix to fc01::/64'] + ['ip6 daddr', f'@N6_{network_group}', 'snat prefix to fc01::/64'], + ['ether saddr', f'@M_{mac_group}', 'snat prefix to fc01::/64'], ] self.verify_nftables(nftables_search, 'ip6 vyos_nat') diff --git a/src/conf_mode/nat66.py b/src/conf_mode/nat66.py index aea187d18..c3637c6b9 100755 --- a/src/conf_mode/nat66.py +++ b/src/conf_mode/nat66.py @@ -92,10 +92,14 @@ def verify(nat): if prefix != None: if not is_ipv6(prefix): raise ConfigError(f'{err_msg} source-prefix not specified') - + + if 'source' in config and 'group' in config['source']: + if len({'address_group', 'network_group', 'domain_group'} & set(config['source']['group'])) > 1: + raise ConfigError('Only one source address-group, network-group or domain-group can be specified') + if 'destination' in config and 'group' in config['destination']: if len({'address_group', 'network_group', 'domain_group'} & set(config['destination']['group'])) > 1: - raise ConfigError('Only one address-group, network-group or domain-group can be specified') + raise ConfigError('Only one destination address-group, network-group or domain-group can be specified') if dict_search('destination.rule', nat): for rule, config in dict_search('destination.rule', nat).items(): @@ -112,9 +116,13 @@ def verify(nat): if not interface_exists(interface_name): Warning(f'Interface "{interface_name}" for destination NAT66 rule "{rule}" does not exist!') + if 'source' in config and 'group' in config['source']: + if len({'address_group', 'network_group', 'domain_group'} & set(config['source']['group'])) > 1: + raise ConfigError('Only one source address-group, network-group or domain-group can be specified') + if 'destination' in config and 'group' in config['destination']: if len({'address_group', 'network_group', 'domain_group'} & set(config['destination']['group'])) > 1: - raise ConfigError('Only one address-group, network-group or domain-group can be specified') + raise ConfigError('Only one destination address-group, network-group or domain-group can be specified') return None |
