Ipv6 prefix NAT

Hi all,

I am using OpenWRT on different TP-Link routers, mostly 3600. Since I have 2 internal /64 networks and 2 access providers I ended up with Masquerading also for ipv6. This has a big disadvantage: my son's steam downloader opens up 20 tcp-connections and this saturates the TP-Link routers' CPU when doing Masquerading for ipv6.

So I installed OpenWrt 24.10.0 as a virtual machine (KVM/Qemu) on a Linux host. This machine has enough CPU power but I am still thinking ipv6 Masquerading is not very elegant.

I assume that the CPU is much less loaded if it doesn't have to do Masquerading but re-writes ipv6 prefixes only.

What do I get from my providers:

Protocol: DHCPv6 client
Prefix Delegated: xxxx:xxxx:343c:b800::/56
Address: xxxx:xxxx:15:2c8d:a12a:522f:e590:f81e/64
Gateway: fe80::xxxx:bff:feec:d883
Expires: 19h 11m 39s
Connected: 3d 16h 48m 36s
Device: Tunnel Interface: "pppoe-wan"

Internally I have ... say ...
2001:db8:100:1::/64
2001:db8:100:2::/64

These nets are announced internally by another machine.

I'd like to achive that whenever the interface gets up OR it gets a new DHCPv6 address or prefix that for outgoing packets
2001:db8:100:1::/64 will be prefix-translated to xxxx:xxxx:343c:b801::/64
2001:db8:100:2::/64 will be prefix-translated to xxxx:xxxx:343c:b802::/64

I am afraid this is not achievabe with the GUI and it might become tricky to change the rule whenever the WAN interface gets a new address and a new delegated prefix

However, I think this is a real world problem since there are many sites using private ipv6 addresses internally because they need static ipv6 addresses but can't afford or get an official /56 or /48.

Any ideas?

You'll find these useful:
https://openwrt.org/docs/guide-user/network/ipv6/ipv6_extras#using_ipv6_by_default
https://openwrt.org/docs/guide-user/network/ipv6/ipv6_extras#disabling_ipv6_source_filter
https://openwrt.org/docs/guide-user/firewall/fw3_configurations/fw3_ipv6_examples#dynamic_prefix_forwarding
However even with these I am not sure you can do the 1-1 translations from Luci.

No, this is not the direction from in to out. I am making progress with creating the nft-rule.
But I have to find out first where I have to place the update script within /etc/hotplug.d

My solution is:

  • Switch off ipv6 masquerading in the firewall wan zone
  • /etc/hotplug.d/iface/40-nat-pt.sh
#!/bin/sh

# depends: gq, bc, tr, sed

[ "$ACTION" = ifup -o "$ACTION" = ifupdate ] || exit 0

ME=`basename "$0"`

(
IF6="wan_6"
CONF="/tmp/ipv6-pt-table.conf"
TABLE="ipv6-pt-table"

DPFX=`ifstatus ${IF6} | jq -r '.["ipv6-prefix"][0].address'`

if [ -z `echo "$DPFX" | grep '::'` ]
then
  echo "no delegated ipv6-prefix for $IF6"
  exit 0
fi

DPFX=`echo "$DPFX" | sed s/::$//`
MASK=`ifstatus ${IF6} | jq -r '.["ipv6-prefix"][0].mask'`
DEVC6=`ifstatus ${IF6} | jq -r '.device'`

if [ "$MASK" -gt 62 ]
then
  echo "mask $MASK too big"
  exit 0
fi

cat <<EOF >$CONF
table inet $TABLE {
  chain ipv6-pt-chain {
    type nat hook postrouting priority srcnat; policy accept;
EOF

LC=`echo "$DPFX" | sed 's/.*://'`
PC=`echo "$DPFX" | sed "s/${LC}\$//"`

ULC=`echo "$LC" | tr 'a-z' 'A-Z'`
UPC=`echo "$PC" | tr 'a-z' 'A-Z'`

for SPFX in 2001:db8:100:1 2001:db8:100:2
do
  ULC=`echo "obase=16; ibase=16; ${ULC}+1" | bc`
  S="${SPFX}::/64"
  D=`echo "${UPC}${ULC}::/64" | tr '[A-Z]' '[a-z]'`

  echo "    oifname \"$DEVC6\" ip6 saddr $S snat ip6 prefix to $D" >>$CONF
done

cat <<EOF >>$CONF
  }
}
EOF

echo "generated $CONF"

nft -f $CONF
nft flush table inet $TABLE
nft -f $CONF
) 2>&1 | logger -t "$ME"

Why do you use NAT and not NPT?

The generated table is:

table inet ipv6-pt-table {
  chain ipv6-pt-chain {
    type nat hook postrouting priority srcnat; policy accept;
    oifname "pppoe-wan" ip6 saddr 2001:db8:42:35::/64 snat ip6 prefix to 2a02:6d40:343c:f101::/64
    oifname "pppoe-wan" ip6 saddr 2001:db8:42:5a::/64 snat ip6 prefix to 2a02:6d40:343c:f102::/64
  }
}

I thought that is NPT since the local part of the addresses is unchanged when going out to the internet.

Did I do it wrong? How would the table look like with NPT then?

No. Sorry. I wrongly recalled memory.
Indead. NPT is just netfilter SNAT magic.
I just use a slighly different syntax:

oifname "pppoe-wan" \
snat ip6 prefix to ip6 saddr map \
  { <non-gua>::/64 : <gua>::/64 }

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