diff options
author | Nicolás Fort <95703796+nicolas-fort@users.noreply.github.com> | 2024-01-04 12:49:39 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-04 15:49:39 +0000 |
commit | 3fc76505d0642c32a3eae9c0ce6ab3dd2ec32dbd (patch) | |
tree | 2b99041737bab239bb97f878213b51c281d74eb1 | |
parent | 1043859f6f87ed64c88c2cd15d4b24a881e89eb1 (diff) | |
download | vyos-1x-3fc76505d0642c32a3eae9c0ce6ab3dd2ec32dbd.tar.gz vyos-1x-3fc76505d0642c32a3eae9c0ce6ab3dd2ec32dbd.zip |
T5159: nat: add option to map network and ports. Feature used for large deployments in cgnat. (#2694)
-rw-r--r-- | python/vyos/nat.py | 10 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_nat.py | 20 | ||||
-rwxr-xr-x | src/conf_mode/nat.py | 5 |
3 files changed, 28 insertions, 7 deletions
diff --git a/python/vyos/nat.py b/python/vyos/nat.py index 392d38772..7215aac88 100644 --- a/python/vyos/nat.py +++ b/python/vyos/nat.py @@ -89,7 +89,10 @@ def parse_nat_rule(rule_conf, rule_id, nat_type, ipv6=False): if addr and is_ip_network(addr): if not ipv6: map_addr = dict_search_args(rule_conf, nat_type, 'address') - translation_output.append(f'{ip_prefix} prefix to {ip_prefix} {translation_prefix}addr map {{ {map_addr} : {addr} }}') + if port: + translation_output.append(f'{ip_prefix} prefix to {ip_prefix} {translation_prefix}addr map {{ {map_addr} : {addr} . {port} }}') + else: + translation_output.append(f'{ip_prefix} prefix to {ip_prefix} {translation_prefix}addr map {{ {map_addr} : {addr} }}') ignore_type_addr = True else: translation_output.append(f'prefix to {addr}') @@ -112,7 +115,10 @@ def parse_nat_rule(rule_conf, rule_id, nat_type, ipv6=False): if port_mapping and port_mapping != 'none': options.append(port_mapping) - translation_str = " ".join(translation_output) + (f':{port}' if port else '') + if ((not addr) or (addr and not is_ip_network(addr))) and port: + translation_str = " ".join(translation_output) + (f':{port}') + else: + translation_str = " ".join(translation_output) if options: translation_str += f' {",".join(options)}' diff --git a/smoketest/scripts/cli/test_nat.py b/smoketest/scripts/cli/test_nat.py index 682fc141d..1e6435df8 100755 --- a/smoketest/scripts/cli/test_nat.py +++ b/smoketest/scripts/cli/test_nat.py @@ -292,5 +292,25 @@ class TestNAT(VyOSUnitTestSHIM.TestCase): self.verify_nftables(nftables_search, 'ip vyos_nat') + def test_snat_net_port_map(self): + self.cli_set(src_path + ['rule', '10', 'protocol', 'tcp_udp']) + self.cli_set(src_path + ['rule', '10', 'source', 'address', '100.64.0.0/25']) + self.cli_set(src_path + ['rule', '10', 'translation', 'address', '203.0.113.0/25']) + self.cli_set(src_path + ['rule', '10', 'translation', 'port', '1025-3072']) + + self.cli_set(src_path + ['rule', '20', 'protocol', 'tcp_udp']) + self.cli_set(src_path + ['rule', '20', 'source', 'address', '100.64.0.128/25']) + self.cli_set(src_path + ['rule', '20', 'translation', 'address', '203.0.113.128/25']) + self.cli_set(src_path + ['rule', '20', 'translation', 'port', '1025-3072']) + + self.cli_commit() + + nftables_search = [ + ['meta l4proto { tcp, udp }', 'snat ip prefix to ip saddr map { 100.64.0.0/25 : 203.0.113.0/25 . 1025-3072 }', 'comment "SRC-NAT-10"'], + ['meta l4proto { tcp, udp }', 'snat ip prefix to ip saddr map { 100.64.0.128/25 : 203.0.113.128/25 . 1025-3072 }', 'comment "SRC-NAT-20"'] + ] + + self.verify_nftables(nftables_search, 'ip vyos_nat') + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py index 20570da62..bd9b5162c 100755 --- a/src/conf_mode/nat.py +++ b/src/conf_mode/nat.py @@ -83,11 +83,6 @@ def verify_rule(config, err_msg, groups_dict): raise ConfigError(f'{err_msg} ports can only be specified when '\ 'protocol is either tcp, udp or tcp_udp!') - if is_ip_network(dict_search('translation.address', config)): - raise ConfigError(f'{err_msg} cannot use ports with an IPv4 network as '\ - 'translation address as it statically maps a whole network '\ - 'of addresses onto another network of addresses!') - for side in ['destination', 'source']: if side in config: side_conf = config[side] |