diff options
| -rw-r--r-- | interface-definitions/include/firewall/nat-balance.xml.i | 2 | ||||
| -rw-r--r-- | interface-definitions/include/nat-rule.xml.i | 4 | ||||
| -rw-r--r-- | python/vyos/nat.py | 8 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_nat.py | 39 | ||||
| -rwxr-xr-x | src/conf_mode/nat.py | 19 | 
5 files changed, 46 insertions, 26 deletions
| diff --git a/interface-definitions/include/firewall/nat-balance.xml.i b/interface-definitions/include/firewall/nat-balance.xml.i index ac60a2545..01793f06b 100644 --- a/interface-definitions/include/firewall/nat-balance.xml.i +++ b/interface-definitions/include/firewall/nat-balance.xml.i @@ -1,5 +1,5 @@  <!-- include start from firewall/nat-balance.xml.i --> -<tagNode name="member"> +<tagNode name="backend">    <properties>      <help>Translated IP address</help>      <valueHelp> diff --git a/interface-definitions/include/nat-rule.xml.i b/interface-definitions/include/nat-rule.xml.i index fa7625c7d..6234e6195 100644 --- a/interface-definitions/include/nat-rule.xml.i +++ b/interface-definitions/include/nat-rule.xml.i @@ -25,9 +25,9 @@      </node>      #include <include/generic-disable-node.xml.i>      #include <include/nat-exclude.xml.i> -    <node name="balance"> +    <node name="load-balance">        <properties> -        <help>Apply NAT balance</help> +        <help>Apply NAT load balance</help>        </properties>        <children>          #include <include/firewall/firewall-hashing-parameters.xml.i> diff --git a/python/vyos/nat.py b/python/vyos/nat.py index 9978993a7..a56ca1ff3 100644 --- a/python/vyos/nat.py +++ b/python/vyos/nat.py @@ -90,12 +90,12 @@ def parse_nat_rule(rule_conf, rule_id, nat_type, ipv6=False):          if options:              translation_str += f' {",".join(options)}' -        if 'member' in rule_conf['balance']: +        if 'backend' in rule_conf['load_balance']:              hash_input_items = []              current_prob = 0              nat_map = [] -            for trans_addr, addr in rule_conf['balance']['member'].items(): +            for trans_addr, addr in rule_conf['load_balance']['backend'].items():                  item_prob = int(addr['weight'])                  upper_limit = current_prob + item_prob - 1                  hash_val = str(current_prob) + '-' + str(upper_limit) @@ -105,10 +105,10 @@ def parse_nat_rule(rule_conf, rule_id, nat_type, ipv6=False):              elements = ' , '.join(nat_map) -            if 'hash' in rule_conf['balance'] and 'random' in rule_conf['balance']['hash']: +            if 'hash' in rule_conf['load_balance'] and 'random' in rule_conf['load_balance']['hash']:                  translation_str += ' numgen random mod 100 map ' + '{ ' + f'{elements}' + ' }'              else: -                for input_param in rule_conf['balance']['hash']: +                for input_param in rule_conf['load_balance']['hash']:                      if input_param == 'source-address':                          param = 'ip saddr'                      elif input_param == 'destination-address': diff --git a/smoketest/scripts/cli/test_nat.py b/smoketest/scripts/cli/test_nat.py index 673be9905..f0c4fef2e 100755 --- a/smoketest/scripts/cli/test_nat.py +++ b/smoketest/scripts/cli/test_nat.py @@ -231,6 +231,27 @@ class TestNAT(VyOSUnitTestSHIM.TestCase):          self.verify_nftables(nftables_search, 'ip vyos_static_nat') +    def test_dnat_redirect(self): +        dst_addr_1 = '10.0.1.1' +        dest_port = '5122' +        protocol = 'tcp' +        redirected_port = '22' +        ifname = 'eth0' + +        self.cli_set(dst_path + ['rule', '10', 'destination', 'address', dst_addr_1]) +        self.cli_set(dst_path + ['rule', '10', 'destination', 'port', dest_port]) +        self.cli_set(dst_path + ['rule', '10', 'protocol', protocol]) +        self.cli_set(dst_path + ['rule', '10', 'inbound-interface', ifname]) +        self.cli_set(dst_path + ['rule', '10', 'translation', 'redirect', 'port', redirected_port]) + +        self.cli_commit() + +        nftables_search = [ +            [f'iifname "{ifname}"', f'ip daddr {dst_addr_1}', f'{protocol} dport {dest_port}', f'redirect to :{redirected_port}'] +        ] + +        self.verify_nftables(nftables_search, 'ip vyos_nat') +      def test_nat_balance(self):          ifname = 'eth0'          member_1 = '198.51.100.1' @@ -246,17 +267,17 @@ class TestNAT(VyOSUnitTestSHIM.TestCase):          self.cli_set(dst_path + ['rule', '1', 'inbound-interface', ifname])          self.cli_set(dst_path + ['rule', '1', 'protocol', 'tcp'])          self.cli_set(dst_path + ['rule', '1', 'destination', 'port', dst_port]) -        self.cli_set(dst_path + ['rule', '1', 'balance', 'hash', 'source-address']) -        self.cli_set(dst_path + ['rule', '1', 'balance', 'hash', 'source-port']) -        self.cli_set(dst_path + ['rule', '1', 'balance', 'hash', 'destination-address']) -        self.cli_set(dst_path + ['rule', '1', 'balance', 'hash', 'destination-port']) -        self.cli_set(dst_path + ['rule', '1', 'balance', 'member', member_1, 'weight', weight_1]) -        self.cli_set(dst_path + ['rule', '1', 'balance', 'member', member_2, 'weight', weight_2]) +        self.cli_set(dst_path + ['rule', '1', 'load-balance', 'hash', 'source-address']) +        self.cli_set(dst_path + ['rule', '1', 'load-balance', 'hash', 'source-port']) +        self.cli_set(dst_path + ['rule', '1', 'load-balance', 'hash', 'destination-address']) +        self.cli_set(dst_path + ['rule', '1', 'load-balance', 'hash', 'destination-port']) +        self.cli_set(dst_path + ['rule', '1', 'load-balance', 'backend', member_1, 'weight', weight_1]) +        self.cli_set(dst_path + ['rule', '1', 'load-balance', 'backend', member_2, 'weight', weight_2])          self.cli_set(src_path + ['rule', '1', 'outbound-interface', ifname]) -        self.cli_set(src_path + ['rule', '1', 'balance', 'hash', 'random']) -        self.cli_set(src_path + ['rule', '1', 'balance', 'member', member_3, 'weight', weight_3]) -        self.cli_set(src_path + ['rule', '1', 'balance', 'member', member_4, 'weight', weight_4]) +        self.cli_set(src_path + ['rule', '1', 'load-balance', 'hash', 'random']) +        self.cli_set(src_path + ['rule', '1', 'load-balance', 'backend', member_3, 'weight', weight_3]) +        self.cli_set(src_path + ['rule', '1', 'load-balance', 'backend', member_4, 'weight', weight_4])          self.cli_commit() diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py index dea833cf1..fa6fe9bb6 100755 --- a/src/conf_mode/nat.py +++ b/src/conf_mode/nat.py @@ -125,17 +125,17 @@ def verify_rule(config, err_msg, groups_dict):                  if config['protocol'] not in ['tcp', 'udp', 'tcp_udp']:                      raise ConfigError('Protocol must be tcp, udp, or tcp_udp when specifying a port-group') -    if 'balance' in config: +    if 'load_balance' in config:          for item in ['source-port', 'destination-port']: -            if item in config['balance']['hash'] and config['protocol'] not in ['tcp', 'udp']: +            if item in config['load_balance']['hash'] and config['protocol'] not in ['tcp', 'udp']:                  raise ConfigError('Protocol must be tcp or udp when specifying hash ports')          count = 0 -        if 'member' in config['balance']: -            for member in config['balance']['member']: -                weight = config['balance']['member'][member]['weight'] +        if 'backend' in config['load_balance']: +            for member in config['load_balance']['backend']: +                weight = config['load_balance']['backend'][member]['weight']                  count = count +  int(weight)              if count != 100: -                Warning(f'Sum of weight for nat balance rule is not 100. You may get unexpected behaviour') +                Warning(f'Sum of weight for nat load balance rule is not 100. You may get unexpected behaviour')  def get_config(config=None):      if config: @@ -210,7 +210,7 @@ def verify(nat):                  Warning(f'rule "{rule}" interface "{config["outbound_interface"]}" does not exist on this system')              if not dict_search('translation.address', config) and not dict_search('translation.port', config): -                if 'exclude' not in config and 'member' not in config['balance']: +                if 'exclude' not in config and 'backend' not in config['load_balance']:                      raise ConfigError(f'{err_msg} translation requires address and/or port')              addr = dict_search('translation.address', config) @@ -222,7 +222,6 @@ def verify(nat):              # common rule verification              verify_rule(config, err_msg, nat['firewall_group']) -      if dict_search('destination.rule', nat):          for rule, config in dict_search('destination.rule', nat).items():              err_msg = f'Destination NAT configuration error in rule {rule}:' @@ -233,8 +232,8 @@ def verify(nat):              elif config['inbound_interface'] not in 'any' and config['inbound_interface'] not in interfaces():                  Warning(f'rule "{rule}" interface "{config["inbound_interface"]}" does not exist on this system') -            if not dict_search('translation.address', config) and not dict_search('translation.port', config): -                if 'exclude' not in config and 'member' not in config['balance']: +            if not dict_search('translation.address', config) and not dict_search('translation.port', config) and not dict_search('translation.redirect.port', config): +                if 'exclude' not in config and 'backend' not in config['load_balance']:                      raise ConfigError(f'{err_msg} translation requires address and/or port')              # common rule verification | 
