NAT6/masq6 broken on OpenWrt 22.03.2?

Hey folks,

My router receives a global IPv6 /64 address, and I'd like to use it for masquerading/NATting my other devices behind it. I've followed the instructions at the ipv6.nat6 wiki page and everything worked fine up until 21.02.2.

With the upgrade to fw4 / nftables, my old NAT66 setup stopped working, as it was issuing iptables commands directly. According to @jow in this thread, just enabling option masq6 1 on the wan zone should work:

In my experience, I can ping ipv6 destinations just fine directly from the router, but when I try to do the same from a computer behind the NAT, the pings fail with ICMPv6 replies from the router saying: Destination unreachable: No route. But on the router I can clearly see the default route:

# ip -f inet6 route
default from 2001:xxxx:xxxx:xxxx::/64 via fe80::xxxx:xxxx:xxxx dev wan  metric 512 
default from fdaa:xxxx:xxxx::/64 via fe80::xxxx:xxxx:xxxx dev wan  metric 512 
...

I've tried tcpdump on the br-lan interface, and I can see the pings coming in, but it's all quiet on the outgoing wan interface.

I see the masquerade rule added in the srcnat_wan chain, as expected:

# nft list chain inet fw4 srcnat_wan
table inet fw4 {
	chain srcnat_wan {
		meta nfproto ipv4 masquerade comment "!fw4: Masquerade IPv4 wan traffic"
		meta nfproto ipv6 masquerade comment "!fw4: Masquerade IPv6 wan traffic"
	}
}

I've also tried tracing the packets through nftables, and I can see the packet making its way through the prerouting chain and getting the verdict "accept", but it never makes it to the forward chain, let alone the postrouting chain, so it never seems to reach the srcnat_wan chain mentioned above.

Not sure if it's relevant, but I've also tried the IPv6 relaying setup, and everything works as expected then, so whatever's broken in the IPv6 forwarding code seems to be specific to masquerading/NAT6.

Any ideas?

local diffs from the default config
diff --git a/etc/config/dhcp b/etc/config/dhcp
index 9553de4..a4a60c2 100644
--- a/etc/config/dhcp
+++ b/etc/config/dhcp
@@ -26,6 +26,7 @@ config dhcp 'lan'
        option dhcpv4 'server'
        option dhcpv6 'server'
        option ra 'server'
+       option ra_default '1'
        option ra_slaac '1'
        list ra_flags 'managed-config'
        list ra_flags 'other-config'
diff --git a/etc/config/firewall b/etc/config/firewall
index b9a4647..9c9f75d 100644
--- a/etc/config/firewall
+++ b/etc/config/firewall
@@ -21,6 +21,7 @@ config zone
        option output           ACCEPT
        option forward          REJECT
        option masq             1
+       option masq6            1
        option mtu_fix          1
 
 config forwarding
diff --git a/etc/config/network b/etc/config/network
index 2379e5c..54ce490 100644
--- a/etc/config/network
+++ b/etc/config/network
@@ -6,7 +6,7 @@ config interface 'loopback'
        option netmask '255.0.0.0'
 
 config globals 'globals'
-       option ula_prefix 'fdac:6ef2:ec66::/48'
+       option ula_prefix 'caca:baba:dada::/48'
 
 config device
        option name 'br-lan'
@@ -19,7 +19,7 @@ config device
 config interface 'lan'
        option device 'br-lan'
        option proto 'static'
-       option ipaddr '192.168.1.1'
+       option ipaddr '192.168.88.1'
        option netmask '255.255.255.0'
        option ip6assign '60'

/etc/config/network
config interface 'loopback'
	option device 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

config globals 'globals'
	option ula_prefix 'caca:baba:dada::/48'

config device
	option name 'br-lan'
	option type 'bridge'
	list ports 'lan1'
	list ports 'lan2'
	list ports 'lan3'
	list ports 'lan4'

config interface 'lan'
	option device 'br-lan'
	option proto 'static'
	option ipaddr '192.168.88.1'
	option netmask '255.255.255.0'
	option ip6assign '60'

config device
	option name 'wan'
	option macaddr 'xx:xx:xx:xx:xx:xx'

config interface 'wan'
	option device 'wan'
	option proto 'dhcp'

config interface 'wan6'
	option device 'wan'
	option proto 'dhcpv6'


/etc/config/firewall
config defaults
	option syn_flood	1
	option input		ACCEPT
	option output		ACCEPT
	option forward		REJECT
# Uncomment this line to disable ipv6 rules
#	option disable_ipv6	1

config zone
	option name		lan
	list   network		'lan'
	option input		ACCEPT
	option output		ACCEPT
	option forward		ACCEPT

config zone
	option name		wan
	list   network		'wan'
	list   network		'wan6'
	option input		REJECT
	option output		ACCEPT
	option forward		REJECT
	option masq		1
	option masq6		1
	option mtu_fix		1

config forwarding
	option src		lan
	option dest		wan

# We need to accept udp packets on port 68,
# see https://dev.openwrt.org/ticket/4108
config rule
	option name		Allow-DHCP-Renew
	option src		wan
	option proto		udp
	option dest_port	68
	option target		ACCEPT
	option family		ipv4

# Allow IPv4 ping
config rule
	option name		Allow-Ping
	option src		wan
	option proto		icmp
	option icmp_type	echo-request
	option family		ipv4
	option target		ACCEPT

config rule
	option name		Allow-IGMP
	option src		wan
	option proto		igmp
	option family		ipv4
	option target		ACCEPT

# Allow DHCPv6 replies
# see https://github.com/openwrt/openwrt/issues/5066
config rule
	option name		Allow-DHCPv6
	option src		wan
	option proto		udp
	option dest_port	546
	option family		ipv6
	option target		ACCEPT

config rule
	option name		Allow-MLD
	option src		wan
	option proto		icmp
	option src_ip		fe80::/10
	list icmp_type		'130/0'
	list icmp_type		'131/0'
	list icmp_type		'132/0'
	list icmp_type		'143/0'
	option family		ipv6
	option target		ACCEPT

# Allow essential incoming IPv6 ICMP traffic
config rule
	option name		Allow-ICMPv6-Input
	option src		wan
	option proto	icmp
	list icmp_type		echo-request
	list icmp_type		echo-reply
	list icmp_type		destination-unreachable
	list icmp_type		packet-too-big
	list icmp_type		time-exceeded
	list icmp_type		bad-header
	list icmp_type		unknown-header-type
	list icmp_type		router-solicitation
	list icmp_type		neighbour-solicitation
	list icmp_type		router-advertisement
	list icmp_type		neighbour-advertisement
	option limit		1000/sec
	option family		ipv6
	option target		ACCEPT

# Allow essential forwarded IPv6 ICMP traffic
config rule
	option name		Allow-ICMPv6-Forward
	option src		wan
	option dest		*
	option proto		icmp
	list icmp_type		echo-request
	list icmp_type		echo-reply
	list icmp_type		destination-unreachable
	list icmp_type		packet-too-big
	list icmp_type		time-exceeded
	list icmp_type		bad-header
	list icmp_type		unknown-header-type
	option limit		1000/sec
	option family		ipv6
	option target		ACCEPT

config rule
	option name		Allow-IPSec-ESP
	option src		wan
	option dest		lan
	option proto		esp
	option target		ACCEPT

config rule
	option name		Allow-ISAKMP
	option src		wan
	option dest		lan
	option dest_port	500
	option proto		udp
	option target		ACCEPT


### EXAMPLE CONFIG SECTIONS
# do not allow a specific ip to access wan
#config rule
#	option src		lan
#	option src_ip	192.168.45.2
#	option dest		wan
#	option proto	tcp
#	option target	REJECT

# block a specific mac on wan
#config rule
#	option dest		wan
#	option src_mac	00:11:22:33:44:66
#	option target	REJECT

# block incoming ICMP traffic on a zone
#config rule
#	option src		lan
#	option proto	ICMP
#	option target	DROP

# port redirect port coming in on wan to lan
#config redirect
#	option src			wan
#	option src_dport	80
#	option dest			lan
#	option dest_ip		192.168.16.235
#	option dest_port	80
#	option proto		tcp

# port redirect of remapped ssh port (22001) on wan
#config redirect
#	option src		wan
#	option src_dport	22001
#	option dest		lan
#	option dest_port	22
#	option proto		tcp

### FULL CONFIG SECTIONS
#config rule
#	option src		lan
#	option src_ip	192.168.45.2
#	option src_mac	00:11:22:33:44:55
#	option src_port	80
#	option dest		wan
#	option dest_ip	194.25.2.129
#	option dest_port	120
#	option proto	tcp
#	option target	REJECT

#config redirect
#	option src		lan
#	option src_ip	192.168.45.2
#	option src_mac	00:11:22:33:44:55
#	option src_port		1024
#	option src_dport	80
#	option dest_ip	194.25.2.129
#	option dest_port	120
#	option proto	tcp

/etc/config/dhcp

config dnsmasq
	option domainneeded '1'
	option boguspriv '1'
	option filterwin2k '0'
	option localise_queries '1'
	option rebind_protection '1'
	option rebind_localhost '1'
	option local '/lan/'
	option domain 'lan'
	option expandhosts '1'
	option nonegcache '0'
	option authoritative '1'
	option readethers '1'
	option leasefile '/tmp/dhcp.leases'
	option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
	option nonwildcard '1'
	option localservice '1'
	option ednspacket_max '1232'

config dhcp 'lan'
	option interface 'lan'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option dhcpv4 'server'
	option dhcpv6 'server'
	option ra 'server'
	option ra_default '1'
	option ra_slaac '1'
	list ra_flags 'managed-config'
	list ra_flags 'other-config'

config dhcp 'wan'
	option interface 'wan'
	option ignore '1'

config odhcpd 'odhcpd'
	option maindhcp '0'
	option leasefile '/tmp/hosts/odhcpd'
	option leasetrigger '/usr/sbin/odhcpd-update'
	option loglevel '4'

Thanks in advance for any help.