summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2026-01-05 16:12:50 +0100
committerGitHub <noreply@github.com>2026-01-05 16:12:50 +0100
commit0da5b3c18ef56ab13cabbbf874f41e8c5b35a518 (patch)
tree35ec3a0d999f977718b26ec5e6507b935148c7e0
parent1fc20e61560d26abec5277a62a318070c8596437 (diff)
parent95f40d8b30f03a47b022042ed8b3c179b0e7abdf (diff)
downloadvyos-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.in2
-rwxr-xr-xsmoketest/scripts/cli/test_nat66.py18
-rwxr-xr-xsrc/conf_mode/nat66.py14
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