Page MenuHomeVyOS Platform

NAT66 source rule with negation source/destination prefix causes TypeError
Closed, ResolvedPublicBUG

Description

When using a negation prefix in NAT66 source rule user will receive an error

Traceback (most recent call last):
  File "/usr/libexec/vyos/conf_mode/nat66.py", line 127, in <module>
    generate(c)
  File "/usr/libexec/vyos/conf_mode/nat66.py", line 101, in generate
    render(nftables_nat66_config, 'firewall/nftables-nat66.j2', nat, permission=0o755)
  File "/usr/lib/python3/dist-packages/vyos/template.py", line 142, in render
    rendered = render_to_string(template, content, formater, location)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/vyos/template.py", line 111, in render_to_string
    rendered = template.render(content)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "/usr/share/vyos/templates/firewall/nftables-nat66.j2", line 28, in top-level template code
    {{ config | nat_rule(rule, 'source', ipv6=True) }}
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/vyos/template.py", line 660, in nat_rule
    return parse_nat_rule(rule_conf, rule_id, nat_type, ipv6)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/vyos/nat.py", line 153, in parse_nat_rule
    addr_prefix = addr[1:]
                  ~~~~^^^^
TypeError: 'NoneType' object is not subscriptable

This is because the code on 153 was likely copy/pasted from the IPv4 code above, which works because a NAT44 rule AND a NAT66 destination rule uses address instead of prefix. Whereas ONLY a NAT66 source rule uses prefix

Intended configuration

set nat66 source rule 10 description 'NAT exclude loopbacks'
set nat66 source rule 10 destination prefix '!fd12:3456:789a:ffff::/64'
set nat66 source rule 10 outbound-interface 'eth0'
set nat66 source rule 10 source prefix 'fd12:3456:c0de:1::/64'

nat66 {
    source {
        rule 10 {
            description "NAT exclude loopbacks"
            destination {
                prefix !fd12:3456:789a:ffff::/64
            }
            outbound-interface eth0
            source {
                prefix fd12:3456:c0de:1::/64
            }
            translation {
                address masquerade
            }
        }
}

Solution is simply to change Ln 153 to addr_prefix = addr_prefix[1:]

Presumably this exists in all versions, so backport would be good as well.

Details

Difficulty level
Easy (less than an hour)
Version
1.5-rolling-202310200118
Why the issue appeared?
Will be filled on close
Is it a breaking change?
Perfectly compatible
Issue type
Bug (incorrect behavior)

Event Timeline

yzguy updated the task description. (Show Details)
yzguy renamed this task from NAT66 rule with negation source/destination prefix errors to NAT66 source rule with negation source/destination prefix causes TypeError.Oct 23 2023, 3:41 AM
yzguy updated the task description. (Show Details)
DEBUG - Traceback (most recent call last):
DEBUG -   File "/usr/libexec/vyos/conf_mode/nat66.py", line 127, in <module>
DEBUG -     generate(c)
DEBUG -   File "/usr/libexec/vyos/conf_mode/nat66.py", line 101, in generate
DEBUG -     render(nftables_nat66_config, 'firewall/nftables-nat66.j2', nat, permission=0o755)
DEBUG -   File "/usr/lib/python3/dist-packages/vyos/template.py", line 142, in render
DEBUG -     rendered = render_to_string(template, content, formater, location)
DEBUG -                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
DEBUG -   File "/usr/lib/python3/dist-packages/vyos/template.py", line 111, in render_to_string
DEBUG -     rendered = template.render(content)
DEBUG -                ^^^^^^^^^^^^^^^^^^^^^^^^
DEBUG -   File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 1301, in render
DEBUG -     self.environment.handle_exception()
DEBUG -   File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 936, in handle_exception
DEBUG -     raise rewrite_traceback_stack(source=source)
DEBUG -   File "/usr/share/vyos/templates/firewall/nftables-nat66.j2", line 28, in top-level template code
DEBUG -     {{ config | nat_rule(rule, 'source', ipv6=True) }}
DEBUG -     ^^^^^^^^^^^^^^^^^^^^^^^^^
DEBUG -   File "/usr/lib/python3/dist-packages/vyos/template.py", line 660, in nat_rule
DEBUG -     return parse_nat_rule(rule_conf, rule_id, nat_type, ipv6)
DEBUG -            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
DEBUG -   File "/usr/lib/python3/dist-packages/vyos/nat.py", line 58, in parse_nat_rule
DEBUG -     oiface = rule_conf['outbound_interface']['interface_group']
DEBUG -              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
DEBUG - TypeError: string indices must be integers, not 'str'

This happens on Line 58 which is well before the change in this PR which is line 173

It's related to https://vyos.dev/T5643

Configuration shared seems to work correctly on latest version:

vyos@Upstream# run show config comm | grep nat66
set nat66 source rule 10 description 'NAT exclude loopbacks'
set nat66 source rule 10 destination prefix '!fd12:3456:789a:ffff::/64'
set nat66 source rule 10 outbound-interface name 'eth1'
set nat66 source rule 10 source prefix 'fd12:3456:c0de:1::/64'
set nat66 source rule 10 translation address 'masquerade'
[edit]
vyos@Upstream# sudo nft list table ip6 vyos_nat
table ip6 vyos_nat {
        chain PREROUTING {
                type nat hook prerouting priority dstnat; policy accept;
                counter packets 0 bytes 0 jump VYOS_DNPT_HOOK
        }

        chain POSTROUTING {
                type nat hook postrouting priority srcnat; policy accept;
                counter packets 0 bytes 0 jump VYOS_SNPT_HOOK
                oifname "eth1" ip6 saddr fd12:3456:c0de:1::/64 ip6 daddr != fd12:3456:789a:ffff::/64 counter packets 0 bytes 0 masquerade comment "SRC-NAT66-10"
        }

        chain VYOS_DNPT_HOOK {
                return
        }

        chain VYOS_SNPT_HOOK {
                return
        }
}
[edit]
vyos@Upstream# run show ver | grep Ver
Version:          VyOS 1.5-rolling-202312191154
[edit]
vyos@Upstream#

Can you re-check and confirm if this is solved @yzguy ?

All good from my side! Just did quick test and it seems to work as expected. Thanks @n.fort