summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViacheslav Hletenko <v.gletenko@vyos.io>2024-06-18 09:47:57 -0500
committerViacheslav Hletenko <v.gletenko@vyos.io>2024-06-19 09:24:42 +0000
commit93cac8a6fdc0a7da50c193e4afcbfe9dec124581 (patch)
tree2be51066dcd63c91d0c2ad9adb9e917bdfe8d2ea
parent14dd6e5deeb7b3b0b81264bac06d92e86b5b91be (diff)
downloadvyos-1x-93cac8a6fdc0a7da50c193e4afcbfe9dec124581.tar.gz
vyos-1x-93cac8a6fdc0a7da50c193e4afcbfe9dec124581.zip
T6497: CGNAT delete conntrack entries if a pool is modified
-rwxr-xr-xsrc/conf_mode/nat_cgnat.py51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/conf_mode/nat_cgnat.py b/src/conf_mode/nat_cgnat.py
index cb336a35c..34ec64fce 100755
--- a/src/conf_mode/nat_cgnat.py
+++ b/src/conf_mode/nat_cgnat.py
@@ -23,6 +23,7 @@ from sys import exit
from logging.handlers import SysLogHandler
from vyos.config import Config
+from vyos.configdict import is_node_changed
from vyos.template import render
from vyos.utils.process import cmd
from vyos.utils.process import run
@@ -118,6 +119,41 @@ class IPOperations:
+ [self.ip_network.broadcast_address]
]
+ def get_prefix_by_ip_range(self):
+ """Return the common prefix for the address range
+
+ Example:
+ % ip = IPOperations('100.64.0.1-100.64.0.5')
+ % ip.get_prefix_by_ip_range()
+ 100.64.0.0/29
+ """
+ if '-' in self.ip_prefix:
+ ip_start, ip_end = self.ip_prefix.split('-')
+ start_ip = ipaddress.IPv4Address(ip_start.strip())
+ end_ip = ipaddress.IPv4Address(ip_end.strip())
+
+ start_int = int(start_ip)
+ end_int = int(end_ip)
+
+ # XOR to find differing bits
+ xor = start_int ^ end_int
+
+ # Count the number of leading zeros in the XOR result to find the prefix length
+ prefix_length = 32 - xor.bit_length()
+
+ # Calculate the network address
+ network_int = start_int & (0xFFFFFFFF << (32 - prefix_length))
+ network_address = ipaddress.IPv4Address(network_int)
+
+ return f"{network_address}/{prefix_length}"
+ return self.ip_prefix
+
+
+def _delete_conntrack_entries(source_prefixes: list) -> None:
+ """Delete all conntrack entries for the list of prefixes"""
+ for source_prefix in source_prefixes:
+ run(f'conntrack -D -s {source_prefix}')
+
def generate_port_rules(
external_hosts: list,
@@ -188,6 +224,9 @@ def get_config(config=None):
with_recursive_defaults=True,
)
+ if conf.exists(base) and is_node_changed(conf, base + ['pool']):
+ config.update({'delete_conntrack_entries': {}})
+
return config
@@ -386,6 +425,18 @@ def apply(config):
# Log error message
logger.error(f"Error processing line '{allocation}': {e}")
+ # Delete conntrack entries
+ if 'delete_conntrack_entries' in config:
+ internal_pool_prefix_list = []
+ for rule, rule_config in config['rule'].items():
+ internal_pool = rule_config['source']['pool']
+ internal_ip_ranges: list = config['pool']['internal'][internal_pool]['range']
+ for internal_range in internal_ip_ranges:
+ ip_prefix = IPOperations(internal_range).get_prefix_by_ip_range()
+ internal_pool_prefix_list.append(ip_prefix)
+ # Deleta required sources for conntrack
+ _delete_conntrack_entries(internal_pool_prefix_list)
+
if __name__ == '__main__':
try: