NAT64 is a gateway that allows IPv6-only clients to reach IPv4-only servers by translating IPv6 addresses to IPv4 addresses on the fly.
Let’s see it in action. Imagine an IPv6-only client, 2001:db8:1::100, trying to access a classic IPv4 web server at 192.0.2.1.
Here’s a simplified packet flow:
-
Client sends to NAT64 gateway: The client constructs an IPv6 packet. The destination address is a special IPv6 prefix that the NAT64 gateway understands, often in the format
64:ff9b::/96followed by the IPv4 address. So,2001:db8:1::100sends a packet to64:ff9b::192.0.2.1. The source address is the client’s IPv6 address,2001:db8:1::100. -
NAT64 gateway receives: The NAT64 gateway, let’s say with IPv6 address
64:ff9b::1and an internal IPv4 address192.168.1.1, receives the packet. -
Address translation: The gateway looks at the destination IPv6 address
64:ff9b::192.0.2.1. It strips off the64:ff9b::prefix, leaving the IPv4 address192.0.2.1. It then rewrites the packet:- Source IP: Changes from
2001:db8:1::100to its own internal IPv4 address,192.168.1.1. - Destination IP: Remains
192.0.2.1. - Port: The gateway typically uses Network Address Translation (NAT) to map the client’s source IPv6 address and port to an internal IPv4 address and a unique port. For example, if the client used UDP port 54321, the gateway might map this to its IPv4 address
192.168.1.1on UDP port 34567.
- Source IP: Changes from
-
Forward to IPv4 server: The translated IPv4 packet is sent to the destination IPv4 server
192.0.2.1. -
Server replies: The IPv4 server
192.0.2.1receives the packet from192.168.1.1(the NAT64 gateway’s IPv4 address). It sends a reply back to192.168.1.1. -
NAT64 gateway receives reply: The gateway receives the IPv4 reply.
-
Reverse translation: The gateway consults its NAT translation table. It finds the mapping for
192.168.1.1and port 34567, which corresponds to the original client2001:db8:1::100and port 54321. It rewrites the packet:- Source IP: Changes from
192.168.1.1to the IPv6 equivalent of the original destination,64:ff9b::192.0.2.1. - Destination IP: Changes from
192.168.1.1to the client’s IPv6 address,2001:db8:1::100. - Port: The original client port
54321is restored.
- Source IP: Changes from
-
Forward to IPv6 client: The translated IPv6 packet is sent back to the client
2001:db8:1::100.
This seamless translation is powered by the Stateless IP/ICMP Translation (SIIT) algorithm, which defines the mapping between IPv6 and IPv4 addresses. There are two primary forms:
- Stateful NAT64: The gateway maintains a table of active translations, just like traditional NAT. This is common for TCP and UDP.
- Stateless NAT64: The translation is purely algorithmic. The IPv6 address is constructed by prepending a fixed prefix (like
64:ff9b::/96) to the IPv4 address. No state is stored on the gateway for this part, making it highly scalable. However, it relies on the client and server using the same ports for the reverse translation to work without a state table. When combined with DNS64, it can handle both stateful and stateless scenarios.
The DNS64 server is a crucial partner in the NAT64 ecosystem. When an IPv6-only client tries to resolve an IPv4-only domain name (e.g., example.com), the DNS64 server intercepts the request. If the DNS server would normally return an A record (IPv4 address), the DNS64 server synthesizes an AAAA record (IPv6 address). This synthesized IPv6 address is formed by taking the IPv4 address and prepending the NAT64 prefix (e.g., 64:ff9b::/96). So, an A record for 192.0.2.1 would result in a DNS64 returning a synthetic AAAA record for 64:ff9b::192.0.2.1. The IPv6-only client then uses this synthetic IPv6 address, which is routed to the NAT64 gateway.
The most surprising true thing about NAT64 is that it doesn’t require the NAT64 gateway to maintain session state for stateless translation to work, provided the DNS64 synthesizes addresses correctly and the client/server use predictable ports. The translation is entirely derived from the address itself.
Consider a scenario where you have an IPv6-only client network with the prefix 2001:db8:1::/64. Your NAT64 gateway has an IPv6 address 64:ff9b::1 and an internal IPv4 address 192.168.1.1. The NAT64 prefix configured on your gateway is 64:ff9b::/96.
If an IPv6 client 2001:db8:1::100 tries to reach 198.51.100.50 (an IPv4 server), the DNS64 server would return the synthetic IPv6 address 64:ff9b::198.51.100.50. The client sends a packet to this destination. The NAT64 gateway receives it. It strips 64:ff9b:: to get 198.51.100.50. It then maps the client’s source 2001:db8:1::100:xxxx (where xxxx is a port) to its own IPv4 address 192.168.1.1 and a new port, say yyyy. The packet is sent as src=192.168.1.1:yyyy, dst=198.51.100.50. The IPv4 server replies to 192.168.1.1:yyyy. The NAT64 gateway sees the reply, looks up 192.168.1.1:yyyy in its table (or reconstructs it if stateless), finds it maps to 2001:db8:1::100:xxxx, and sends the packet back.
The critical component that most people overlook is the DNS64 server. Without it, IPv6-only clients wouldn’t even know how to form the synthetic IPv6 addresses that NAT64 translates. It acts as the bridge on the DNS layer, making IPv4 resources appear as IPv6 resources to the IPv6-only clients.
The next logical step after understanding NAT64 is exploring DNS64 configuration and its interaction with BIND or CoreDNS.