NAT46 - Workarounds Beyond Reverse Proxy?

Started by vivekmauli14, July 22, 2025, 01:25:25 PM

Previous topic - Next topic
Hi,

I am having a unique requirement of NAT46 at one of my user, I'm aware that Linux-based machines like Jool or TAYGA support NAT46 via TUN/TAP interfaces or netfilter hooks. I'm hoping to either replicate that behavior natively with any native tool or find a more flexible workaround than an L7 reverse proxy. Any insights, documentation links, or experimental solutions would be very helpful — happy to test patches or contribute to development if needed.

Thanks in advance!

Best,
VivekSP

Tayga is available on OPNsense as a plugin, but the GUI currently only allows configuring it as a NAT64. Other configurations are possible through scripts though.

What is your use case? Do you need a CLAT on OPNsense (as one side of a 464XLAT setup)? Or do want to make a specific IPv6 service available via IPv4?

Cheers
Maurice
OPNsense virtual machine images
OPNsense aarch64 firmware repository

Commercial support & engineering available. PM for details (en / de).

Hi,
Thanks for reverting! The user wants :

IPv4 clients must be able to reach a specific IPv6-only service on my internal network. This means the firewall needs to perform a NAT46 translation on inbound traffic. An external IPv4 client would send a request to a public IPv4 address on the box, and the firewall would translate that to the correct IPv6 address of my internal service.
looking forward for guidance to make this work reliably and securely within the environment.

Thanks again!

Best,
VivekSP

July 23, 2025, 09:14:42 AM #3 Last Edit: July 23, 2025, 11:03:30 AM by Monviech (Cedrik)
This might be a stupid question from me, but why no dual stack on the internal network?

At first glance it sounds more complicated to work around dual stack than just embracing it for as long as its needed.

I know reverse proxies are not always ideal, but you can also proxy directly on layer4:

https://docs.opnsense.org/manual/how-tos/caddy.html#layer-4-matchers

relayd might also do it? I never tried it though.

https://docs.opnsense.org/manual/relayd.html#relayd
Hardware:
DEC740

Hi Maurice,

I tried this configuration but didnt work as expected. The goal was to translate traffic from IPv4 address (192.0.2.66) to a real internal IPv6 address (fd00:abcd::10).

 Tayga startup script
#!/bin/sh
# /root/start-tayga46.sh

echo "[*] Cleaning up any previous NAT46 instance..."
ifconfig nat46 destroy 2>/dev/null
killall tayga 2>/dev/null

echo "[*] Starting TAYGA and waiting for it to create the nat46 interface..."
/usr/local/sbin/tayga -c /usr/local/etc/tayga46.conf &

# Poll for the interface to appear
INTERFACE_EXISTS=false
for i in $(seq 1 10); do
    if ifconfig nat46 >/dev/null 2>&1; then
        echo "[+] Interface nat46 created by Tayga."
        INTERFACE_EXISTS=true
        break
    fi
    sleep 0.5
done

if [ "$INTERFACE_EXISTS" = false ]; then
    echo "[!] TAYGA failed to create the interface. Aborting."
    exit 1
fi


# Configure the Proxmox interface with its IPv6 address.
ifconfig igc2 inet6 fd00:abcd::1/64 alias

# Configure the IPv4 side of the tunnel.
ifconfig nat46 inet 192.0.2.1 192.0.2.2 netmask 255.255.255.255 up

# Configure the IPv6 side of the tunnel using our new dedicated network.
ifconfig nat46 inet6 fd00:aabb::2 fd00:aabb::1 prefixlen 128 up

echo "[*] Adding NAT46 routes..."

# This route directs traffic for the fake IPv4 network to Tayga.
route add -inet 192.0.2.0/24 -iface nat46



and Tayga config

# /usr/local/etc/tayga46.conf

tun-device nat46

ipv4-addr 192.0.2.1

ipv6-addr fd00:aabb::1

map 192.0.2.66 fd00:abcd::10

data-dir /var/db/tayga46


When I run a packet capture, I can see that Tayga is translating the packets correctly! The initial packet from the client gets translated from IPv4 to IPv6, and the destination server sends back a [S.] (SYN-ACK) reply.

16:38:20.035896 IP 192.0.2.1.1612 > 192.0.2.66.8082: Flags [S], seq 729630911, win 65228, options [mss 1460,nop,wscale 7,sackOK,TS val 3783615226 ecr 0], length 0
16:38:20.035929 IP6 fd00:aabb::1.1612 > fd00:abcd::10.8082: Flags [S], seq 729630911, win 65228, options [mss 1460,nop,wscale 7,sackOK,TS val 3783615226 ecr 0], length 0
16:38:20.035955 IP6 fd00:abcd::10.8082 > fd00:aabb::1.1612: Flags [S.], seq 2602201702, ack 729630912, win 0, options [mss 1460], length 0

The connection stalls immediately. As you can see in the third packet, the IPv6 server (fd00:abcd::10) is responding with a TCP win 0.and the TCP handshake never completes and no data can be transferred.

what could be causing this win 0 response? Does this point to a problem in my Tayga/network configuration, or is it more likely an issue on the destination server (fd00:abcd::10) that is incompatible with the translated packet it's receiving? or is it the compatibility issue of PF with tayga NAT46?

As Monviech suggested, I may try relayd or caddy as an alternative, but I'd love to understand why this is failing.

Thank you all !

Hi Monviech,

I guess our version of caddy does not have layer4 module for my usecase of NAT46 workaround


root@Marge:/usr/local/etc/caddy/caddy.d # caddy list-modules | grep layer4
root@Marge:/usr/local/etc/caddy/caddy.d #


Trying with relayd, will update here..

Thanks


Hey,

which OPNsense version do you currently use?
Hardware:
DEC740