NAT64 and DNS64 are complementary IPv6 transition mechanisms that enable IPv6-only clients to communicate with IPv4-only servers. As networks increasingly adopt IPv6-only architectures to avoid the complexities of dual-stack deployments, NAT64/DNS64 provides a critical bridge to maintain backward compatibility with the legacy IPv4 internet.
Key RFC specifications:
These mechanisms work together seamlessly: DNS64 synthesizes IPv6 addresses for IPv4 destinations, while NAT64 performs the actual protocol translation, allowing IPv6-only networks to access the vast IPv4 internet without requiring IPv6 support from destination servers.
NAT64 is a stateful network address and protocol translation mechanism that converts IPv6 packets to IPv4 and vice versa. It operates as a gateway device positioned at the network edge, translating between the two protocol families.
Primary function: Enable IPv6-only clients to initiate connections to IPv4-only servers using standard protocols (TCP, UDP, ICMPv6).
Translation method: Stateful NAT64 maintains connection state tables, mapping IPv6 client addresses to IPv4 addresses dynamically. This allows bidirectional communication while preserving application-layer protocols.
[IPv6 Client] → [NAT64 Gateway] → [IPv4 Server]
Step 1: IPv6 client sends packet to 64:ff9b::192.0.2.10
Source: 2001:db8::1234
Destination: 64:ff9b::192.0.2.10
Step 2: NAT64 gateway receives packet
- Allocates IPv4 address from pool (e.g., 203.0.113.5)
- Extracts IPv4 destination from lower 32 bits
- Creates state table entry
Step 3: NAT64 translates and forwards to IPv4
Source: 203.0.113.5 (NAT64 pool)
Destination: 192.0.2.10 (extracted from IPv6)
[IPv4 Server] → [NAT64 Gateway] → [IPv6 Client]
Step 1: IPv4 server responds
Source: 192.0.2.10
Destination: 203.0.113.5
Step 2: NAT64 looks up state table
- Finds mapping: 203.0.113.5 → 2001:db8::1234
- Prepends NAT64 prefix to source IPv4
Step 3: NAT64 translates and forwards to IPv6
Source: 64:ff9b::192.0.2.10
Destination: 2001:db8::1234
Stateful NAT64 (RFC 6146):
Stateless NAT64 (RFC 7915):
DNS64 is a DNS server extension that synthesizes AAAA records (IPv6 addresses) from A records (IPv4 addresses) when no native IPv6 address exists for a domain. It acts as a DNS proxy that intercepts queries and manufactures IPv6 addresses pointing to the NAT64 gateway.
Primary function: Provide IPv6 addresses to clients even when destination servers only support IPv4.
Synthesis algorithm: DNS64 combines a configured IPv6 prefix (typically 64:ff9b::/96) with the IPv4 address found in A records, creating a synthetic AAAA record.
[IPv6 Client] → [DNS64 Server] → [Authoritative DNS] → [DNS64 Server] → [IPv6 Client]
Step 1: Client queries for www.example.com AAAA record
Query: "What is the IPv6 address for www.example.com?"
Step 2: DNS64 forwards query to authoritative DNS
- Checks for native AAAA record first
- If AAAA exists: returns it directly (no synthesis)
- If no AAAA: queries for A record
Step 3: Authoritative DNS returns A record only
Response: www.example.com → 192.0.2.10 (A record)
Step 4: DNS64 synthesizes AAAA record
- Takes NAT64 prefix: 64:ff9b::/96
- Embeds IPv4 address in lower 32 bits
- Creates synthetic AAAA: 64:ff9b::192.0.2.10
Step 5: DNS64 returns synthetic AAAA to client
Response: www.example.com → 64:ff9b::192.0.2.10 (AAAA)
Query for domain AAAA record:
│
├─ Native AAAA exists?
│ ├─ YES → Return native AAAA (no synthesis)
│ └─ NO → Continue to A record lookup
│
├─ A record exists?
│ ├─ YES → Synthesize AAAA from A record
│ │ (Prefix + IPv4 → IPv6 address)
│ └─ NO → Return NXDOMAIN (no records found)
│
└─ Return synthetic AAAA to client
Important: DNS64 always prioritizes native IPv6 addresses. Synthesis only occurs when a domain has A records but no AAAA records.
The well-known prefix (WKP) 64:ff9b::/96 is reserved by RFC 6052 specifically for NAT64/DNS64 deployments. This standardized prefix allows clients and network equipment to recognize NAT64-synthesized addresses globally.
Prefix breakdown:
64:ff9b:: /96
│
├─ 96 bits: NAT64 prefix (fixed)
└─ 32 bits: Embedded IPv4 address (variable)
Example:
64:ff9b::192.0.2.10
│ └─ IPv4: 192.0.2.10 embedded in lower 32 bits
└─ Prefix: 64:ff9b::/96
IPv4 addresses are embedded in the lower 32 bits of the synthetic IPv6 address:
IPv4 Address: 192.0.2.10
Hexadecimal: C0 00 02 0A
IPv6 Embedding: 64:ff9b::C000:020A
Expanded form: 64:ff9b::192.0.2.10
Well-Known Prefix (64:ff9b::/96):
Network-Specific Prefix (Custom /96):
Example NSP usage:
NSP: 2001:db8:64::/96
IPv4: 10.0.1.50 (private RFC 1918)
Synthetic IPv6: 2001:db8:64::10.0.1.50
┌─────────────────────────────────────────────────────────────────────┐
│ IPv6-Only Network │
│ │
│ ┌──────────────┐ │
│ │ IPv6 Client │ │
│ │2001:db8::1234│ │
│ └──────┬───────┘ │
│ │ 1. DNS query: www.ipv4only.com AAAA? │
│ ↓ │
│ ┌──────────────┐ │
│ │ DNS64 Server │ │
│ │ │←──2. Query authoritative DNS for AAAA │
│ │ │←──3. Receive A record: 192.0.2.10 │
│ │ │ 4. Synthesize: 64:ff9b::192.0.2.10 │
│ └──────┬───────┘ │
│ │ 5. Return AAAA: 64:ff9b::192.0.2.10 │
│ ↓ │
│ ┌──────────────┐ │
│ │ IPv6 Client │ │
│ │ │ │
│ └──────┬───────┘ │
│ │ 6. HTTP GET to 64:ff9b::192.0.2.10 │
│ │ Src: 2001:db8::1234 │
│ │ Dst: 64:ff9b::192.0.2.10 │
│ ↓ │
│ ┌──────────────────────┐ │
│ │ NAT64 Gateway │ │
│ │ IPv6: 64:ff9b::/96 │ │
│ │ IPv4 pool: x.x.x.x │ │
│ └──────┬───────────────┘ │
│ │ 7. Translate to IPv4 │
└─────────┼─────────────────────────────────────────────────────────┘
│ Src: 203.0.113.5 (from NAT64 pool)
│ Dst: 192.0.2.10 (extracted from IPv6)
↓
┌─────────────────────────────────────────────────────────────────────┐
│ IPv4 Internet │
│ │
│ ┌────────────────────┐ │
│ │ IPv4-Only Server │ │
│ │ 192.0.2.10 │ │
│ │ www.ipv4only.com │ │
│ └────────────────────┘ │
│ │ 8. HTTP response │
│ │ Src: 192.0.2.10 │
│ │ Dst: 203.0.113.5 │
└─────────┼─────────────────────────────────────────────────────────┘
↓
│ 9. NAT64 translates back to IPv6
│ Src: 64:ff9b::192.0.2.10
│ Dst: 2001:db8::1234
↓
[IPv6 Client receives response]
IPv6 Packet (Client → NAT64):
IPv6 Header:
Source: 2001:db8::1234
Destination: 64:ff9b::192.0.2.10
Next Header: TCP
TCP Payload:
GET / HTTP/1.1
Host: www.ipv4only.com
Translated IPv4 Packet (NAT64 → Server):
IPv4 Header:
Source: 203.0.113.5 (NAT64 pool address)
Destination: 192.0.2.10 (extracted from IPv6)
Protocol: TCP
TCP Payload:
GET / HTTP/1.1
Host: www.ipv4only.com
(unchanged application data)
Organizations transitioning to IPv6-only networks deploy NAT64/DNS64 to maintain access to IPv4-only internet services while eliminating dual-stack complexity.
Architecture:
Internal IPv6-Only Network (2001:db8::/32)
│
├─ Workstations ([SLAAC](slaac-explained) addressing)
├─ Servers (static IPv6)
├─ Internal DNS64 server
│ └─ Configured with NSP: 2001:db8:64::/96
│
└─ Border NAT64 gateway
├─ IPv6 interface: 2001:db8:64::1
├─ IPv4 pool: 203.0.113.0/24
└─ Internet uplink
Benefits:
Mobile operators deploy IPv6-only radio access networks with NAT64/DNS64 combined with CLAT (Customer-Side Translator) in devices—known as 464XLAT (RFC 6877).
Architecture:
┌─────────────────┐
│ Mobile Device │
│ (IPv6-only RAN) │
│ │
│ ┌─────────────┐ │
│ │ CLAT │ │ ← Client-side IPv4→IPv6 translation
│ │ (464XLAT) │ │ Presents virtual IPv4 to apps
│ └─────────────┘ │
└────────┬────────┘
│ IPv6 packets
↓
┌────────────────────┐
│ Carrier Network │
│ (IPv6-only core) │
│ │
│ ┌────────────────┐ │
│ │ PLAT (NAT64) │ │ ← Provider-side IPv6→IPv4 translation
│ └────────────────┘ │
└────────┬───────────┘
│ IPv4 packets
↓
IPv4 Internet
Advantages:
Cloud providers (AWS, Google Cloud, Azure) offer IPv6-only instance options with managed NAT64/DNS64 services.
Google Cloud example:
VPC Subnet: 2001:db8:1::/64 (IPv6-only)
│
├─ Cloud DNS64 policy configured
├─ NAT Gateway with NAT64 enabled
│ └─ Uses well-known prefix 64:ff9b::/96
│
└─ Compute instances (IPv6-only)
└─ Can reach IPv4 internet via NAT64
AWS VPC example:
VPC with IPv6 CIDR: 2600:1f14::/56
│
├─ Egress-only Internet Gateway (IPv6)
├─ NAT Gateway with DNS64/NAT64
│ └─ Subnet-level enablement
│
└─ EC2 instances (IPv6-only)
└─ Automatic DNS64 synthesis
Google Public DNS64:
Resolver addresses:
2001:4860:4860::6464
2001:4860:4860::64
Configuration:
- Uses well-known prefix 64:ff9b::/96
- Global anycast service
- Automatic synthesis for IPv6-only clients
Client configuration (Linux):
# /etc/resolv.conf
nameserver 2001:4860:4860::6464
nameserver 2001:4860:4860::64
Testing DNS64:
# Query IPv4-only domain
dig AAAA www.example.com @2001:4860:4860::6464
# Expected response:
# www.example.com. 300 IN AAAA 64:ff9b::93e5:70b
# └─ Synthesized from 147.229.7.11
NAT64 stateful pool:
ipv6 unicast-routing
! Define NAT64 prefix
ipv6 nat prefix 64:ff9b::/96
! Configure NAT64 pool
ipv6 nat v4-pool NAT64_POOL 203.0.113.1 203.0.113.254
! Apply NAT64 to interfaces
interface GigabitEthernet0/0
description IPv6 side
ipv6 address 2001:db8::1/64
ipv6 nat
interface GigabitEthernet0/1
description IPv4 side
ip address 203.0.113.1 255.255.255.0
ipv6 nat
DNS64 configuration:
! Enable DNS64
ipv6 nat prefix 64:ff9b::/96
ipv6 dns64 enable
! DNS64 server configuration
ipv6 dns64 server 2001:db8::53
Jool NAT64 deployment:
# Install Jool kernel module
sudo apt-get install linux-modules-extra-$(uname -r)
sudo modprobe jool
# Configure NAT64 instance
sudo jool instance add "example" --netfilter --pool6 64:ff9b::/96
# Add IPv4 pool
sudo jool -i "example" pool4 add --tcp 203.0.113.1 61001-65535
sudo jool -i "example" pool4 add --udp 203.0.113.1 61001-65535
sudo jool -i "example" pool4 add --icmp 203.0.113.1 61001-65535
# Enable IPv6 forwarding
sudo sysctl -w net.ipv6.conf.all.forwarding=1
BIND9 DNS64 (named.conf):
options {
dns64 64:ff9b::/96 {
clients { any; };
mapped { !2001:db8::/32; any; };
exclude { ::ffff:0000:0000/96; 64:ff9b::/96; };
recursive-only yes;
};
};
464XLAT clients discover NAT64 prefix via Router Advertisements:
# Router Advertisement with PREF64 option (RFC 8781)
radvd.conf:
interface eth0 {
AdvSendAdvert on;
prefix 2001:db8::/64 { };
# PREF64 option for NAT64 prefix discovery
PREF64 64:ff9b::/96 { };
};
Client verification (Linux):
# Check received PREF64
ip -6 route show | grep pref64
# Expected output:
# pref64 64:ff9b::/96 dev eth0 metric 1024 pref medium
IPv4 literal addresses embedded in application data:
Workaround: Application Layer Gateway (ALG) modules or 464XLAT CLAT for client-side translation.
Problem: DNS64 synthesis breaks DNSSEC validation chain.
Authoritative DNS:
example.com A 192.0.2.10 (signed with DNSSEC)
DNS64 synthesis:
example.com AAAA 64:ff9b::192.0.2.10 (NOT signed by domain owner)
Validation result: FAIL (signature mismatch)
Mitigation strategies:
Best practice: Deploy DNS64 as part of trusted recursive DNS infrastructure within the network perimeter.
Latency overhead:
Research findings:
Optimization:
Single point of failure: NAT64 gateway failure breaks IPv4 connectivity for entire IPv6-only network.
High-availability deployment:
IPv6-Only Network
│
┌─────────┴─────────┐
│ │
┌───▼────┐ ┌────▼───┐
│ NAT64 │ │ NAT64 │
│Gateway1│◄───────►│Gateway2│
│(Active)│ VRRP │(Standby)│
└───┬────┘ └────┬───┘
│ │
└─────────┬─────────┘
↓
IPv4 Internet
Load distribution:
Stateful NAT64 efficiency:
Pool exhaustion risks:
Monitoring:
# Jool NAT64 pool statistics
sudo jool -i "example" stats display
# Watch for:
# - Active sessions / pool capacity
# - Port exhaustion warnings
# - Dropped packets due to pool exhaustion
Applications requiring special handling:
Hard-coded IPv4 literals: Applications connecting directly to IPv4 addresses bypass DNS64 entirely.
IPv4-only APIs: Some services lack IPv6 endpoints and require IPv4 connectivity.
Peer-to-peer protocols: NAT64 stateful translation complicates NAT traversal (STUN/TURN).
Network diagnostics: Tools like traceroute require ICMP support through NAT64.
From IPv6-only client:
# Test DNS64 synthesis
dig AAAA ipv4.test-ipv6.run
# Expected: Synthesized AAAA with 64:ff9b:: prefix
# Test NAT64 translation
curl -6 -v http://ipv4.test-ipv6.run/
# Expected: Successful HTTP response via NAT64
# Verify packet translation
traceroute -6 ipv4.test-ipv6.run
# Expected: Path shows 64:ff9b:: addresses
Comprehensive connectivity testing: Visit test-ipv6.run for automated NAT64/DNS64 detection:
Key metrics:
# Connection state table usage
sudo jool -i "example" stats display | grep "Current"
# Translation success rate
sudo jool -i "example" stats display | grep "Successful"
# Pool4 utilization
sudo jool -i "example" pool4 display
Traffic analysis:
# Capture NAT64 translated traffic
sudo tcpdump -i eth0 -n 'ip6 dst 64:ff9b::/96'
# Monitor IPv4 side translations
sudo tcpdump -i eth1 -n 'src net 203.0.113.0/24'
NAT64/DNS64 is a transition mechanism, not an end goal. Always prioritize native IPv6 connectivity:
For internet-facing NAT64:
For internal/private NAT64:
NAT64 and DNS64 provide an elegant solution for IPv6-only networks to maintain backward compatibility with the IPv4 internet. By combining DNS64's address synthesis with NAT64's stateful protocol translation, organizations can deploy IPv6-only infrastructures while seamlessly accessing IPv4-only services.
Key takeaways:
As the internet continues its transition to IPv6, NAT64/DNS64 will remain a critical bridge technology—enabling IPv6-only deployments without sacrificing connectivity to the legacy IPv4 world. However, the ultimate goal remains native IPv6 everywhere, eliminating the need for translation altogether.
Test your network's IPv6 readiness: Visit test-ipv6.run to detect NAT64 deployment, measure connectivity, and receive a comprehensive IPv6 readiness score.