Configuring a dual-stack network with NAT support and ds-lite using conntrack

So a while back I posted a question about setting up a dual stack ipv4 network with PPPoE and ds-lite, and enabling NAT support via PPPoE.
I got a solution that worked perfectly using the PBR package, but since then I've been curious about solving the issue using conntrack instead.
I thought I'd share the solution using OpenWRT for posterity. If someone got extra tips, I'd love to hear!

First, setup route table, pppoe with an id of 100 (both arbitrary) using iproute2:

root@OpenWrt:/etc# cat /etc/iproute2/rt_tables
#
# reserved values
#
128     prelocal
255     local
254     main
253     default
0       unspec
#
# local
#
#1      inr.ruhep
100 pppoe

Next, we need to tell the PPPoE interface to setup a default route in our new table.

root@OpenWrt:/etc# cat /etc/config/network

...

config interface 'PPPoE'
        option proto 'pppoe'
        option device 'wan'
        option username '****'
        option password '****'
        option ipv6 'auto'
        option ip4table 'pppoe' # <--- Here

...

Interestingly, doing this will result in the following routing rules:

root@OpenWrt:~# ip rule
0:      from all lookup local
1:      from all fwmark 0x5 lookup pppoe
10000:  from <public ipv4 address> lookup pppoe
20000:  from all to <public ipv4 address> lookup pppoe
32766:  from all lookup main
32767:  from all lookup default
90014:  from all iif lo lookup pppoe
root@OpenWrt:~# ip route show table pppoe
default via <ipv4 gateway> dev pppoe-PPPoE proto static

All traffic coming from the pppoe interface will be routed using the pppoe routing table, but that table doesn't have any rules for reaching into our bridge lan network. We will add a static route to fix this:

root@OpenWrt:/etc# cat /etc/config/network

...

config route
        option interface 'lan'
        option target '192.168.1.0/24'
        option table 'pppoe'

...

Lastly, we need to setup a rule to drive traffic marked by conntrack to be routed via this routing table:

root@OpenWrt:/etc# cat /etc/config/network

...


config rule
        option mark '0x5'
        option lookup 'pppoe'

...

I arbitrarily chose the mark 0x5. We will set this mark via a custom chain:

root@OpenWrt:~# cat /etc/nftables.d/20-ipv4-routing.nft
# https://serverfault.com/questions/1107846/how-to-route-a-reply-packet-to-the-device-it-coming-from
chain ipv4-preroute {
  type filter hook prerouting priority mangle; policy accept;
  iifname "pppoe-PPPoE" ct state new meta mark set 0x05 ct mark set mark comment "!ipv4_routing: mark connection"
  iifname "br-lan" ct mark 0x05 meta mark set ct mark comment "!ipv4_routing: mark outgoing packets for routing"
}

And that's it! Now, all connections originating via the pppoe interface will be marked with 0x05, and all packets coming in through the lan network, which are part of the marked connection, will be marked with 0x05 and therefore routed via pppoe

2 Likes