The IPv4 Exhaustion Reality
I recently led a migration where we shifted a massive microservices cluster to an IPv6-only infrastructure. We wanted to ditch the headache of managing private IPv4 address overlaps and simplify our routing tables. On paper, it was the perfect architectural move. In production, we ran into immediate roadblocks. Several legacy monitoring agents and proprietary third-party libraries were hardcoded for IPv4. They didn’t recognize AAAA records and couldn’t process a 128-bit address.
This scenario is a common headache in modern DevOps. You need the scalability of IPv6, but the world still clings to legacy protocols. If you have ever tried to run a 10-year-old binary on an IPv6-only host only to see a “Network unreachable” error, you know how frustrating this is.
Why Standard NAT64 Isn’t Always Enough
Most engineers start with NAT64 and DNS64. This combination works well for web browsers or applications that rely strictly on DNS. When an app requests api.example.com, DNS64 synthesizes an IPv6 address, and NAT64 handles the translation. However, this fails when an application has an IP like 1.1.1.1 hardcoded in its config. It also fails with custom protocols that bypass DNS lookups entirely.
The application crashes because it finds no IPv4 stack on the local interface. This is where 464XLAT becomes essential. It provides a logical IPv4 interface on the local machine (the CLAT). This virtual interface tricks the application into thinking it is on a standard IPv4 network, while the actual transport occurs over the IPv6 fabric.
How 464XLAT Works: CLAT and PLAT
464XLAT uses two distinct components to bridge the gap:
- PLAT (Provider-side Translator): This is a NAT64 gateway managed by your provider or core infra team. It translates IPv6 packets back into IPv4 to reach the public internet.
- CLAT (Customer-side Translator): This is the part we configure on our Linux host. It creates a virtual
clatinterface. When an app sends an IPv4 packet, the CLAT wraps it in an IPv6 header and routes it to the PLAT.
I have deployed this setup in environments pushing 10Gbps of traffic. It remains rock-solid. It bridges the protocol gap without requiring developers to rewrite a single line of legacy code.
The Solution: Implementing CLAT with TAYGA
For implementing CLAT on Linux, TAYGA is the gold standard. It is a stateless NAT64 daemon that is incredibly lightweight. TAYGA stays out of the way and focuses on high-speed translation.
Step 1: Prerequisites
Ensure your host has functional IPv6 connectivity and that you know your network’s NAT64 prefix. Most networks use the standard well-known prefix: 64:ff9b::/96.
# Install TAYGA on Debian/Ubuntu
sudo apt update
sudo apt install tayga -y
Step 2: Configuring TAYGA
Open /etc/tayga.conf to define your virtual IPv4 address and the NAT64 prefix. This configuration tells TAYGA how to map the two address spaces.
# Edit /etc/tayga.conf
tun-device nat64
ipv4-addr 192.168.255.1
prefix 64:ff9b::/96
dynamic-pool 192.168.255.0/24
In this config, 192.168.255.1 acts as the internal gateway. The dynamic-pool provides a range of local IPv4 addresses that TAYGA uses to map incoming IPv6 traffic back to the local system.
Step 3: Initializing the Interface
Next, create the network interface and define the routing. We must instruct the Linux kernel to send all IPv4-bound traffic through the TAYGA interface.
# Create the nat64 device
sudo tayga --mktun
# Bring the interface up
sudo ip link set nat64 up
sudo ip addr add 192.168.255.1 dev nat64
# Force all IPv4 traffic through the translation interface
sudo ip route add 0.0.0.0/0 dev nat64
Step 4: Starting the Daemon
Now, start the TAYGA service. Use systemd to ensure the translator restarts automatically if the server reboots.
sudo systemctl enable tayga
sudo systemctl start tayga
Handling Routing and Source IP
Source addresses often confuse newcomers. When an IPv4 packet enters the nat64 interface, TAYGA converts it to IPv6. The new IPv6 source address is a combination of your NAT64 prefix and your internal IPv4 address.
For this to work, you must enable IP forwarding. You also need to verify that your firewall (iptables or nftables) isn’t blocking the translated traffic.
# Enable IPv6 forwarding
sudo sysctl -w net.ipv6.conf.all.forwarding=1
# Allow traffic to flow through the nat64 interface
sudo iptables -A FORWARD -i nat64 -j ACCEPT
sudo iptables -A FORWARD -o nat64 -j ACCEPT
Testing the Translation
To verify the setup, ping a public IPv4-only address. While Google’s DNS (8.8.8.8) supports IPv6, we can use it to force an IPv4-path test.
ping -4 8.8.8.8
If the pings return successfully, your CLAT is working. Your legacy applications will now see a valid IPv4 route and can communicate across the IPv6-only network without issues.
Best Practices from the Field
After managing several IPv6 migrations, I recommend these optimizations to avoid common pitfalls:
- Fix MTU Issues: IPv6 headers are 40 bytes, while IPv4 headers are only 20. This 20-byte difference can cause packets to drop during large transfers. If connections hang, lower your
nat64interface MTU to 1260. - Monitor Logs: TAYGA sends its output to syslog. If connectivity drops, run
tail -f /var/log/syslog. It clearly logs when it cannot find a valid route to the PLAT. - Verify Prefixes: Don’t assume the prefix is
64:ff9b::/96. Some enterprise networks use custom prefixes. Always confirm with your network team or usedig +short amir.ipv6-test.com AAAAto see how the network synthesizes addresses.
Final Thoughts
Transitioning to IPv6 shouldn’t force you to trash reliable legacy software. 464XLAT offers a transparent, high-performance bridge that keeps your infrastructure modern. By using TAYGA as a CLAT daemon, you can maintain a dual-stack environment even when your provider only gives you a single IPv6 address.

