IPv6 NAT in v22.03.0-rc4 with nftables: LAN host no Internet, packets not flowing into forward chain

Hi there. Had a very hard time setting up IPv6 recently. Because my ISP only allocates single IPv6 addresses with limitations (one MAC address can only use the last address allocated from DHCPv6), I had to use NAT6.

  • Device: Redmi AC2100
  • Version: OpenWrt r22.03.0-rc4 (using nftables + firewall4)

I managed to let the router have access to IPv6 Internet, but when I configured masq6 for clients in LAN, the NAT6 does not work.

When I do Wireshark on my PC, it shows that all packets sent to the router for routing were rejected as "Destination Unreachable (no route to the host)". When I went to nftables tracing, I noticed that NO IPv6 PACKET from LAN hosts has ever reached the forward chain. These packets reached the dstnat chain (at prerouting), and disappeared from tracing, returning the PC a "Destination Unreachable". Even I create a new chain hooking at forward with a priority of -1000, no IPv6 packet can be seen.

Factually I managed to make it work yesterday (but I forgot how), but after a router reset, it fails again.

Here's my config:

Network
# /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 packet_steering '1'
        option ula_prefix 'fd76:d462:c4e3::/48'

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

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ipaddr '192.168.1.1'
        option netmask '255.255.255.0'
        option delegate '0'
        option ip6assign '64'

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

config interface 'wan6'
        option device 'wan'
        option proto 'dhcpv6'
        option reqaddress 'try'
        option vendorclass '0000013700084D5346542035102E30'
        option reqprefix 'no'
DHCP
# /etc/config/dhcp
config dnsmasq
        option domainneeded '1'
        option localise_queries '1'
        option rebind_protection '1'
        option rebind_localhost '1'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option authoritative '1'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
        option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
        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 ra 'server'
        option dhcpv6 'server'
        option ra_management '1'
        option ra_default '1'
        option dns_server '0'
        list dns '2001:da8::666'
        list dhcp_option '6,210.28.129.251,210.28.129.252'

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

config odhcpd 'odhcpd'
        option maindhcp '0'
        option leasefile '/tmp/hosts/odhcpd'
        option leasetrigger '/usr/sbin/odhcpd-update'
        option loglevel '4'
Firewall
# /etc/config/firewall
config defaults
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option synflood_protect '1'

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

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

config forwarding
        option src 'lan'
        option dest 'wan'

config rule
        option name 'Allow-DHCP-Renew'
        option src 'wan'
        option proto 'udp'
        option dest_port '68'
        option target 'ACCEPT'
        option family 'ipv4'

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'

config rule
        option name 'Allow-DHCPv6'
        option src 'wan'
        option proto 'udp'
        option family 'ipv6'
        option target 'ACCEPT'
        option dest_port '546-547'

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'

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'

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'

config rule
(an empty rule at the end)

I doubt that there may be conflicting kernel module (legacy ip6tables for example), so here's my lsmod:

lsmod
cfg80211              298812  5 mt7615_common,mt7603e,mt76_connac_lib,mt76,mac80211
cmac                    2546  2 
compat                  1358  2 mac80211,cfg80211,[permanent]
crc_ccitt               1774  1 ppp_async
crc32c_generic          1458  1 
drbg                   17586  0 
gpio_button_hotplug     6674  0 
hmac                    2578  0 
hwmon                   8038  1 mt7615_common
ip_tables              11645  0 
ip6_tables             11331  0 
jitterentropy_rng       7561  0 
leds_gpio               3250  0 
libcrc32c                727  1 nf_tables
libsha256               8772  1 sha256_generic
mac80211              557288  5 mt7615e,mt7615_common,mt7603e,mt76_connac_lib,mt76
mt76                   48100  4 mt7615e,mt7615_common,mt7603e,mt76_connac_lib
mt76_connac_lib        26897  2 mt7615e,mt7615_common
mt7603e                40284  0 
mt7615_common          68934  1 mt7615e
mt7615e                11469  0 
netatop                35215  0 
nf_conntrack           71239  8 nft_redir,nft_nat,nft_masq,nft_flow_offload,nft_ct,nf_nat,nf_flow_table,nf_conntrack_bridge
nf_conntrack_bridge     3346  0 
nf_defrag_ipv4          1273  1 nf_conntrack
nf_defrag_ipv6          6036  2 nf_conntrack_bridge,nf_conntrack
nf_flow_table          23615  4 nf_flow_table_ipv6,nf_flow_table_ipv4,nf_flow_table_inet,nft_flow_offload
nf_flow_table_inet       658  0 
nf_flow_table_ipv4       530  0 
nf_flow_table_ipv6       530  0 
nf_log_common           3064  2 nf_log_ipv6,nf_log_ipv4
nf_log_ipv4             3762  0 
nf_log_ipv6             4050  0 
nf_nat                 24974  4 nft_redir,nft_nat,nft_masq,nft_chain_nat
nf_reject_ipv4          2601  3 nft_reject_ipv4,nft_reject_inet,nft_reject_bridge
nf_reject_ipv6          2926  3 nft_reject_ipv6,nft_reject_inet,nft_reject_bridge
nf_tables             153615203 nft_fib_inet,nf_flow_table_ipv6,nf_flow_table_ipv4,nf_flow_table_inet,nft_reject_ipv6,nft_reject_ipv4,nft_reject_inet,nft_reject_bridge,nft_reject,nft_redir,nft_quota,nft_objref,nft_numgen,nft_nat,nft_meta_bridge,nft_masq,nft_log,nft_limit,nft_hash,nft_flow_offload,nft_fib_ipv6,nft_fib_ipv4,nft_fib,nft_ct,nft_counter,nft_compat,nft_chain_nat
nfnetlink               5761  2 nft_compat,nf_tables
nft_chain_nat            946  2 
nft_compat              5874  0 
nft_counter             2226 18 
nft_ct                  7538  3 
nft_fib                 1622  3 nft_fib_inet,nft_fib_ipv6,nft_fib_ipv4
nft_fib_inet             754  0 
nft_fib_ipv4            2197  1 nft_fib_inet
nft_fib_ipv6            2869  1 nft_fib_inet
nft_flow_offload        3442  0 
nft_hash                2578  0 
nft_limit               3634  5 
nft_log                 1810  0 
nft_masq                1938  2 
nft_meta_bridge         1426  0 
nft_nat                 2738  0 
nft_numgen              1826  0 
nft_objref              1746  0 
nft_quota               2098  0 
nft_redir               1906  0 
nft_reject              1383  4 nft_reject_ipv6,nft_reject_ipv4,nft_reject_inet,nft_reject_bridge
nft_reject_bridge       4178  0 
nft_reject_inet         1234  2 
nft_reject_ipv4          754  0 
nft_reject_ipv6          754  0 
ppp_async               7330  0 
ppp_generic            25903  3 pppoe,ppp_async,pppox
pppoe                   9714  0 
pppox                   1520  1 pppoe
seqiv                   1682  0 
sha256_generic          2557  0 
slhc                    5538  1 ppp_generic
x_tables               17341  3 nft_compat,ip6_tables,ip_tables

sysctl.conf is completely default (Do I need wan.accept_ra = 2 ?):

sysctl
net.core.bpf_jit_enable=1

net.ipv4.conf.default.arp_ignore=1
net.ipv4.conf.all.arp_ignore=1
net.ipv4.ip_forward=1
net.ipv4.icmp_echo_ignore_broadcasts=1
net.ipv4.icmp_ignore_bogus_error_responses=1
net.ipv4.igmp_max_memberships=100
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_keepalive_time=120
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_timestamps=1
net.ipv4.tcp_sack=1
net.ipv4.tcp_dsack=1

net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
nftables ruleset
table inet fw4 {
        chain input {
                type filter hook input priority filter; policy accept;
                iifname "lo" accept comment "!fw4: Accept traffic from loopback"
                ct state established,related accept comment "!fw4: Allow inbound established and related flows"
                tcp flags syn / fin,syn,rst,ack jump syn_flood comment "!fw4: Rate limit TCP syn packets"
                iifname "br-lan" jump input_lan comment "!fw4: Handle lan IPv4/IPv6 input traffic"
                iifname "wan" jump input_wan comment "!fw4: Handle wan IPv4/IPv6 input traffic"
        }

        chain forward {
                type filter hook forward priority filter; policy drop;
                ct state established,related accept comment "!fw4: Allow forwarded established and related flows"
                iifname "br-lan" jump forward_lan comment "!fw4: Handle lan IPv4/IPv6 forward traffic"
                iifname "wan" jump forward_wan comment "!fw4: Handle wan IPv4/IPv6 forward traffic"
                jump handle_reject
        }

        chain output {
                type filter hook output priority filter; policy accept;
                oifname "lo" accept comment "!fw4: Accept traffic towards loopback"
                ct state established,related accept comment "!fw4: Allow outbound established and related flows"
                meta l4proto tcp counter packets 0 bytes 0 comment "!fw4: @rule[9]"
                meta l4proto udp counter packets 27 bytes 2192 comment "!fw4: @rule[9]"
                oifname "br-lan" jump output_lan comment "!fw4: Handle lan IPv4/IPv6 output traffic"
                oifname "wan" jump output_wan comment "!fw4: Handle wan IPv4/IPv6 output traffic"
        }

        chain handle_reject {
                meta l4proto tcp reject with tcp reset comment "!fw4: Reject TCP traffic"
                reject comment "!fw4: Reject any other traffic"
        }

        chain syn_flood {
                limit rate 25/second burst 50 packets return comment "!fw4: Accept SYN packets below rate-limit"
                drop comment "!fw4: Drop excess packets"
        }

        chain input_lan {
                jump accept_from_lan
        }

        chain output_lan {
                jump accept_to_lan
        }

        chain forward_lan {
                jump accept_to_wan comment "!fw4: Accept lan to wan forwarding"
                jump accept_to_lan
        }

        chain accept_from_lan {
                iifname "br-lan" counter packets 252 bytes 19093 accept comment "!fw4: accept lan IPv4/IPv6 traffic"
        }

        chain accept_to_lan {
                oifname "br-lan" counter packets 105 bytes 7472 accept comment "!fw4: accept lan IPv4/IPv6 traffic"
        }

        chain input_wan {
                meta nfproto ipv4 udp dport 68 counter packets 0 bytes 0 accept comment "!fw4: Allow-DHCP-Renew"
                icmp type echo-request counter packets 0 bytes 0 accept comment "!fw4: Allow-Ping"
                meta nfproto ipv4 meta l4proto igmp counter packets 0 bytes 0 accept comment "!fw4: Allow-IGMP"
                meta nfproto ipv6 udp dport 546-547 counter packets 0 bytes 0 accept comment "!fw4: Allow-DHCPv6"
                ip6 saddr fe80::/10 icmpv6 type . icmpv6 code { mld-listener-query . no-route, mld-listener-report . no-route, mld-listener-done . no-route, mld2-listener-report . no-route } counter packets 0 bytes 0 accept comment "!fw4: Allow-MLD"
                icmpv6 type { destination-unreachable, time-exceeded, echo-request, echo-reply, nd-router-solicit, nd-router-advert } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Input"
                icmpv6 type . icmpv6 code { packet-too-big . no-route, parameter-problem . no-route, nd-neighbor-solicit . no-route, nd-neighbor-advert . no-route, parameter-problem . admin-prohibited } limit rate 1000/second counter packets 20 bytes 1440 accept comment "!fw4: Allow-ICMPv6-Input"
                jump reject_from_wan
        }

        chain output_wan {
                jump accept_to_wan
        }

        chain forward_wan {
                icmpv6 type { destination-unreachable, time-exceeded, echo-request, echo-reply } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Forward"
                icmpv6 type . icmpv6 code { packet-too-big . no-route, parameter-problem . no-route, parameter-problem . admin-prohibited } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Forward"
                meta l4proto esp counter packets 0 bytes 0 jump accept_to_lan comment "!fw4: Allow-IPSec-ESP"
                udp dport 500 counter packets 0 bytes 0 jump accept_to_lan comment "!fw4: Allow-ISAKMP"
                jump reject_to_wan
        }

        chain accept_to_wan {
                oifname "wan" counter packets 2123 bytes 133725 accept comment "!fw4: accept wan IPv4/IPv6 traffic"
        }

        chain reject_from_wan {
                iifname "wan" counter packets 0 bytes 0 jump handle_reject comment "!fw4: reject wan IPv4/IPv6 traffic"
        }

        chain reject_to_wan {
                oifname "wan" counter packets 0 bytes 0 jump handle_reject comment "!fw4: reject wan IPv4/IPv6 traffic"
        }

        chain dstnat {
                type nat hook prerouting priority dstnat; policy accept;
        }

        chain srcnat {
                type nat hook postrouting priority srcnat; policy accept;
                oifname "wan" jump srcnat_wan comment "!fw4: Handle wan IPv4/IPv6 srcnat traffic"
        }

        chain srcnat_wan {
                meta nfproto ipv4 masquerade comment "!fw4: Masquerade IPv4 wan traffic"
                meta nfproto ipv6 masquerade comment "!fw4: Masquerade IPv6 wan traffic"
        }

        chain raw_prerouting {
                type filter hook prerouting priority raw; policy accept;
                iifname "br-lan" jump helper_lan comment "!fw4: lan IPv4/IPv6 CT helper assignment"
        }

        chain raw_output {
                type filter hook output priority raw; policy accept;
        }

        chain helper_lan {
        }

        chain mangle_prerouting {
                type filter hook prerouting priority mangle; policy accept;
        }

        chain mangle_postrouting {
                type filter hook postrouting priority mangle; policy accept;
        }

        chain mangle_input {
                type filter hook input priority mangle; policy accept;
        }

        chain mangle_output {
                type route hook output priority mangle; policy accept;
        }

        chain mangle_forward {
                type filter hook forward priority mangle; policy accept;
                iifname "wan" tcp flags syn tcp option maxseg size set rt mtu comment "!fw4: Zone wan IPv4/IPv6 ingress MTU fixing"
                oifname "wan" tcp flags syn tcp option maxseg size set rt mtu comment "!fw4: Zone wan IPv4/IPv6 egress MTU fixing"
        }
}

Any help would be appreciated.

Try to speak to your ISP, this is not how IPv6 is supposed to be deployed. Each end-network should be given a reasonably sized prefix space to implement its own subnetting. There are IETF recommendations like rfc6177 which recommend to assign each end-user network anything larger than a /64 up to a /48... maybe if you read and then cite this towards your ISP they might change their ways...

1 Like

Well, it's my institution network... so no luck here...

However, this should definitely be a problem in my OpenWrt setup (or bug?) since my router can access the Internet.

Not sure it is a good idea to connect multiple devices behind your institutions administrators back, but that is a decision you need to make here. But I have no first-hand experience in regards to your specific question and hence will apologize for the distraction and bow out of this thread, since I can not productively contribute.

1 Like

Well, adding net.ipv6.conf.wan.accept_ra = 2 seems to do the trick. Thanks.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.