diff options
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/nat_cgnat.py | 51 | 
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: | 
