An IPv6-only network still has to reach an internet that is substantially IPv4. The translator that makes that possible is the visible part of the arrangement and it is not the part that makes it work. What makes it work is a name server that answers a question about a name with an address that does not exist — an IPv6 address manufactured on the spot, containing the real IPv4 address inside it, routed to the translator by design.
That is an elegant mechanism and it has one absolute dependency: the client has to ask. Everything that fails on an IPv6-only network with this arrangement fails for the same reason, which is that something skipped the name lookup and used an IPv4 address it already had. The translator is working perfectly throughout.
This article covers what the arrangement is actually solving, how a client learns an address for a server that has none, the difference between the stateless and stateful forms and when each applies, what does not work through it and why the reasons are all the same reason, and how to deploy and verify it. It is written for the lab rather than for the written exam, and sits alongside the rest of the CCIE Enterprise Infrastructure lab certification track.
What Problem Is Being Solved?
What is the situation?
A network where hosts have IPv6 addresses and no IPv4 ones, needing to reach services that have IPv4 addresses and no IPv6 ones. There is no address family in common, so nothing can be routed between them; something has to rewrite the packet from one family into the other. That is the translator's job, and it is only half the problem — the client also needs an IPv6 address to send to, and the server does not have one.
A Deeper Dive into the Problem
Why running both families is the alternative
Giving every host an address in each family removes the problem entirely and doubles the operational surface: two addressing plans, two sets of rules, two routing tables' worth of troubleshooting, and every fault requiring the question of which family it affects.
That cost is the argument for an IPv6-only network with translation at the edge. It is a real argument and it is not free, because the translation introduces its own set of behaviours to understand. The decision is between two kinds of complexity rather than between complexity and simplicity.
Where this actually gets deployed
Mobile networks, at scale, because the address pressure there made IPv6-only unavoidable years ago. Large enterprise guest networks. Data centres where the internal estate is IPv6 and some external dependency is not. And laboratory or campus segments where somebody is doing the transition deliberately.
It is worth knowing that the mobile case runs a further mechanism on the client to handle what this one cannot, which is covered later. A network without that extra piece has a set of failures the mobile networks do not.
The address that does not exist
The client needs an IPv6 destination. The server has only an IPv4 address. The resolution is to manufacture an IPv6 address by taking a prefix that is routed to the translator and putting the server's IPv4 address into the low bits.
Any device holding that address can recover the IPv4 address by arithmetic, with no lookup and no state. That is what makes the destination direction of the translation stateless even in the stateful form: the destination is always derivable from the address itself.
Which prefix
A well-known prefix exists and is reserved for exactly this. It can be used where the traffic stays within one administrative domain, and it has a documented restriction: it must not be used to translate to addresses that are not globally routable, because a packet carrying it could otherwise be routed to a translator in a different network with a different idea of what the embedded address means.
A network-specific prefix from the organisation's own space avoids that entirely and is the right choice for anything other than a simple case. The only cost is using a /96 out of the organisation's allocation, which is negligible.
! Enable translation on both sides and declare the prefix
R1(config)# interface GigabitEthernet0/0
R1(config-if)# description IPv6-only clients
R1(config-if)# nat64 enable
!
R1(config)# interface GigabitEthernet0/1
R1(config-if)# description IPv4 internet
R1(config-if)# nat64 enable
!
R1(config)# nat64 prefix stateful 2001:DB8:64::/96
!
R1# show nat64 prefix stateful
Routing, which has two halves
The IPv6 side must route the prefix to the translator, or clients send to an address nothing carries. The IPv4 side must route the translator's pool back to it, or replies never return. Both are ordinary routing and both are forgotten at least once in every deployment.
The first is usually satisfied by the translator advertising the prefix into the interior routing protocol. The second requires whatever provides IPv4 connectivity to know that the pool lives here, which is the same requirement as any translation deployment.
| Piece | Provides | Fails as |
|---|---|---|
| The manufactured answer | An IPv6 address to send to | Client has nowhere to connect |
| The prefix, routed inward | A path to the translator | Timeouts, translator idle |
| The translator | The rewriting itself | Nothing crosses |
| The pool, routed back | A return path | Entries created, no replies |
How Does a Client Learn an Address?
What does the name server do?
When asked for an IPv6 address for a name that has none, it looks for an IPv4 address instead, and if it finds one it manufactures an IPv6 address by combining the translation prefix with that IPv4 address. It returns that as though it were a real answer. The client has no idea anything unusual happened and connects normally. Every property of the design follows from this being a fabrication performed by the name server rather than anything the client understands.
A Deeper Dive into Name Resolution
The synthesis rule
Only when there is no genuine IPv6 address. A name that has one gets it, unmodified, and the translator is not involved — which is correct, because a service reachable over IPv6 should be reached over IPv6.
That ordering means the mechanism gets quieter over time as more services become reachable natively. It also means a service that gains an IPv6 address silently stops using the translator, which is the intended outcome and occasionally surprises whoever was monitoring translator throughput.
Where the prefix is embedded
At a position determined by the prefix length. With a /96 prefix the IPv4 address occupies the final 32 bits, which is the simplest case and the one to use unless there is a reason not to. Shorter prefixes place the address elsewhere with a documented gap, for reasons rooted in address architecture.
Using a /96 avoids the complication entirely and there is rarely a reason to use anything else. The name server and the translator must agree on the prefix and its length, and a mismatch produces addresses the translator cannot interpret.
! The arithmetic, with a /96 prefix
! prefix 2001:DB8:64::/96
! IPv4 198.51.100.7 = c6 33 64 07 in hex
! result 2001:DB8:64::c633:6407
!
! From a client, the answer looks entirely ordinary
$ dig AAAA www.example.com
www.example.com. 300 IN AAAA 2001:db8:64::c633:6407
!
! On the translator, the same address arriving
R1# show nat64 translations protocol tcp
Clients that discover the prefix themselves
A client can determine the prefix in use by querying a name known to resolve only to an IPv4 address and inspecting what comes back. That allows a client to know it is behind this arrangement and to behave accordingly — which is how the additional client-side mechanism used in mobile networks gets its configuration.
For a network deploying only the server side, this is informational. For one deploying the client-side piece as well, it is how the pieces find each other without configuration.
The conflict with answer validation
A client that validates the name server's answers cryptographically will reject a manufactured one, because the manufactured record was not signed by the zone that owns the name and could not have been. The mechanism and end-to-end validation are fundamentally incompatible for synthesised answers.
Practically this means the resolver performs validation and the client does not, which works and moves the trust to the resolver. A client configured to validate for itself will find names that resolve to nothing on this network, and the failure looks like a name resolution problem rather than a design conflict.
Where the resolver sits
The synthesising resolver must be the one clients use, which means it is the address handed out by the network. A client configured with a public resolver that does not synthesise receives no IPv6 answer for an IPv4-only name and cannot connect.
That is worth anticipating, because configuring a public resolver is a common thing for people to do on their own machines, and on this network it breaks everything reachable only over IPv4 while leaving everything else working.
Verifying the resolver side independently
Query the resolver directly for a name known to have only an IPv4 address and confirm that an IPv6 answer comes back containing the expected prefix. That tests the whole name half without involving the translator at all.
Doing that first, before investigating connectivity, separates the two halves of the design cleanly. A resolver that is not synthesising produces a failure that no amount of translator configuration will fix.
! Test the two halves separately. Resolver first.
$ dig @2001:db8::53 AAAA ipv4only.example.com
! Expect an answer containing your prefix. If not, stop here.
!
! Then the translator, with a literal synthesised address
$ ping6 2001:db8:64::c633:6407
!
! And on the translator, confirm it saw it
R1# show nat64 statistics | include Packets translated|v6 to v4
Stateless or Stateful?
Which applies?
Stateful, almost always. It maps many IPv6 hosts onto a small pool of IPv4 addresses using ports, exactly as ordinary address translation does, and places no constraint on how the IPv6 hosts are addressed. The stateless form maps one to one by arithmetic in both directions, which requires every IPv6 host to be addressed out of a prefix that embeds its own IPv4 address, and one IPv4 address per host. That is a strong constraint and it suits a small set of controlled cases.
A Deeper Dive into the Two Forms
What stateless requires
Each IPv6 host's address must itself contain an IPv4 address, so that the translation is pure arithmetic in both directions with no table. That means the IPv6 addressing plan is derived from an IPv4 addressing plan, which is a substantial constraint on a network that was meant to be leaving IPv4 behind.
It buys two things: no state, so no table to exhaust and no failover problem, and inbound connections without configuration. Where a set of servers must be reachable from both families and the address arithmetic is acceptable, it is a clean fit.
What stateful requires
A pool of IPv4 addresses and a table. The IPv6 addressing is unconstrained. Sessions are distinguished by port exactly as in ordinary translation, so a small pool serves a large population.
The costs are the familiar ones: a table that can fill, no inbound connections without a static mapping, and a failover that discards everything. Those are the same trades as any address translation and they are well understood.
! Stateful: a pool, a selection list, and overloading
R1(config)# ipv6 access-list NAT64-SOURCES
R1(config-ipv6-acl)# permit ipv6 2001:DB8:10::/48 any
!
R1(config)# nat64 v4 pool NAT64-POOL 203.0.113.10 203.0.113.14
R1(config)# nat64 v6v4 list NAT64-SOURCES pool NAT64-POOL overload
!
R1# show nat64 statistics | include pool|Total
R1# show nat64 translations protocol tcp
! Stateless: arithmetic both ways, no table, no pool
R1(config)# nat64 prefix stateless 2001:DB8:64::/96
R1(config)# nat64 route 0.0.0.0/0 GigabitEthernet0/1
!
! A specific server, reachable from both families
R1(config)# nat64 v4v6 static 203.0.113.30 2001:DB8:64::cb00:711e
!
R1# show nat64 prefix stateless
Publishing a service inward
An IPv6-only server that must be reachable from IPv4 clients needs a mapping from an IPv4 address to it. That is configured explicitly and is the mirror of a static mapping in ordinary translation.
The IPv4 address used must be routed to the translator, and the service's name must have an IPv4 record pointing at it. Both halves are needed and the second is frequently the one that was not arranged, which produces a service that is reachable by address and not by name.
! Publish an IPv6-only service to IPv4 clients
R1(config)# nat64 v6v4 static 2001:DB8:10::80 203.0.113.30
!
! Or one service rather than the whole host
R1(config)# nat64 v6v4 static tcp 2001:DB8:10::80 443 203.0.113.5 443
!
! The name also needs an A record pointing at 203.0.113.30,
! or the service is reachable by address and not by name.
R1# show nat64 translations protocol tcp | include 203.0.113.30
Sizing the pool
The same calculation as any overloaded translation: concurrent conversations divided by the ports available per address. The population is typically large on the networks where this is deployed, which makes the calculation worth doing rather than guessing.
The failure when it is undersized is identical to ordinary translation exhaustion — existing sessions work, nothing new can start — and so are the remedies: shorter timeouts, a per-host cap, and more addresses.
! Same pressures as any overloaded translation
R1(config)# nat64 translation timeout tcp 3600
R1(config)# nat64 translation timeout udp 120
R1(config)# nat64 translation timeout icmp 30
R1(config)# nat64 translation max-entries all-host 300
!
R1# show nat64 statistics | include Total active|limit|Dropped
Hairpinning
Two IPv6 hosts behind the same translator communicating via a translated address — one of them reaching the other by the address the outside world uses. The specification requires the translator to handle this, and it is worth testing, because it is the case a deployment will hit when an internal client reaches an internal service by its public name.
Where it does not work, the answer is the same as in ordinary translation: internal name resolution returning the internal address, so the traffic never attempts the round trip.
The MTU consideration
The two families have different header sizes and different minimum packet sizes, so translation changes the length of every packet and the translator has to make decisions about what to do with packets that no longer fit.
The practical effect is the familiar one: small packets pass and large ones can fail, particularly where the notifications that would tell a sender to reduce its size are filtered. Setting a conservative size on the client-facing side avoids it, and testing with a large packet confirms it. Reading this once is not the same as being able to do it under time pressure, which is what repetition against realistic CCIE lab practice scenarios is for.
What Does Not Work Through It?
What is the common cause?
Skipping the name lookup. An application using a hard-coded IPv4 address has no name to resolve, so nothing manufactures an address and the client has nowhere to send. An application that asks specifically for an IPv4 address gets a real one, which on an IPv6-only network is unreachable. A protocol carrying addresses in its payload sends IPv4 addresses that the IPv6 side cannot use. Every one of those is the same failure: the mechanism only works for traffic that went through name resolution and asked for IPv6.
A Deeper Dive into the Failures
Hard-coded addresses
A configuration file naming a server by IPv4 address, a link containing an address instead of a name, an application with a built-in default. All of them bypass the resolver entirely, and on an IPv6-only network the address they produce cannot be sent to.
This is common in enterprise environments, where internal tooling and older applications frequently refer to things by address. It is the single largest obstacle to an IPv6-only enterprise network and it is an application inventory problem rather than a network one.
The client-side mechanism that fixes it
A component on the client that presents an IPv4 interface to applications and translates locally into IPv6, which is then translated back at the network edge. An application using a hard-coded IPv4 address talks to a local IPv4 stack that exists solely for it, and the traffic reaches the far end correctly.
This is what mobile networks run and it is why IPv6-only works there for applications that would otherwise fail. Deploying it on managed enterprise endpoints is feasible; deploying it on arbitrary devices is not, which is the practical limit.
Applications that ask for the wrong family
An application that requests an IPv4 address specifically receives the real one, because the resolver answers that question honestly. It then attempts a connection the network cannot carry.
Modern libraries request both and prefer what works, which handles this correctly. Older applications and anything written against an IPv4-only assumption do not, and the failure is at the application rather than anywhere the network can address.
Addresses inside payloads
Protocols carrying addresses in their data have the same problem here as with ordinary translation, with an additional difficulty: the address in the payload is the wrong family entirely, not merely the wrong value. Rewriting it means converting between families inside the application data.
Helpers exist for the common cases and the coverage is thinner than for ordinary translation. A protocol that carries addresses and has no helper will not work, and the answer is either to fix the application or to reach that service over IPv4 by some other route.
Traffic that is not the common protocols
The translation covers the widely used transport protocols and the diagnostic messages. Traffic using something else may not be translated, and diagnostic message types that exist in one family and not the other cannot be mapped cleanly.
That last point matters for troubleshooting: a diagnostic reply may not survive translation, so a failed test does not always mean a failed path. Testing with an ordinary connection rather than only with diagnostics gives a more reliable answer.
What to inventory before deploying
Applications referring to things by address rather than by name. Applications requesting IPv4 specifically. Protocols carrying addresses in their data. And anything with an IPv4 literal in its configuration, which is the largest category and the one nobody has a list of.
Building that list before an IPv6-only rollout is most of the work, and discovering it afterwards one application at a time is how these projects acquire a reputation.
! Test each class separately, from a client
$ dig AAAA server.example.com # synthesised? then the path exists
$ curl -6 https://server.example.com/ # by name, over v6
$ curl https://198.51.100.7/ # by literal - this is the one that fails
!
! And on the translator, see which ones arrived
R1# show nat64 statistics | include translated|Dropped
R1# show nat64 translations | count 2001:DB8:10
| What fails | Because | Fixed by |
|---|---|---|
| Hard-coded IPv4 address | No lookup occurred | Use a name, or client-side translation |
| Application asks for IPv4 | It gets a real, unreachable address | Fix the application |
| Address in the payload | No helper, or wrong family | A helper, or another route |
| Client validates answers itself | Synthesised answers cannot be signed | Validate at the resolver |
| Client uses a public resolver | It does not synthesise | Enforce the network's resolver |
How Do You Deploy and Verify It?
What is the order?
Prefix chosen and routed inward. Translator configured and its pool routed back. Resolver configured to synthesise, and verified independently by querying it. Then a client test by literal synthesised address, which exercises the translator without the resolver, followed by a test by name, which exercises both. Then the application inventory, which is the long part. Each stage is verifiable on its own and failing to separate them is what makes the first deployment confusing.
A Deeper Dive into Deployment
Choosing and routing the prefix
A /96 from the organisation's own allocation, advertised into the interior routing protocol by the translator. Every IPv6 client segment must have a path to it, and the check is a route lookup from a client segment rather than an assumption.
Using the well-known prefix is acceptable for simple single-domain cases and carries a documented restriction about what it may translate to. Using an organisation prefix avoids the question and costs nothing.
The two routing halves, verified separately
From the IPv6 side, confirm a route exists for the prefix pointing toward the translator. From the IPv4 side, confirm the pool range is routed to the translator by whatever provides IPv4 connectivity. Each is one command and each is a common omission.
! Both halves, checked from the right places
Client# show ipv6 route 2001:DB8:64::
!
Upstream# show ip route 203.0.113.10
!
! And on the translator itself
R1# show nat64 prefix stateful
R1# show nat64 statistics | include pool
Testing the translator without the resolver
Compute a synthesised address by hand for a known IPv4 destination and send to it directly from a client. If that works, the prefix routing, the translator and the pool routing are all correct, and any remaining problem is in name resolution.
That single test separates the two halves of the design definitively and takes a minute. It is the most useful diagnostic step available and it is rarely the first thing anyone tries.
Testing the resolver without the translator
Query the resolver for a name known to have only an IPv4 address and confirm an IPv6 answer comes back containing the prefix. The translator is not involved and does not need to be working.
Between this and the previous test, every failure is attributable before any connectivity troubleshooting begins.
What to monitor
The translation count against the pool's capacity, which is the exhaustion measure. The count of packets dropped by the translator, whose growth indicates traffic arriving that cannot be translated. And the resolver's synthesis rate, which shows how much of the network still depends on the mechanism — and should fall over time as services gain native connectivity.
The third is the one that tells you whether the transition is progressing. A synthesis rate that is not falling means the services being used are not adopting IPv6, which is useful information for anyone planning the next phase.
! Three numbers worth collecting
R1# show nat64 statistics | include Total active|Limit
R1# show nat64 statistics | include Dropped|Unsupported
!
! And from the resolver, how much is still being synthesised
! (resolver-specific; the trend is what matters, not the absolute)
The failover question
The stateful form holds a table, so a failover to a second translator breaks every conversation exactly as ordinary translation does. Where session survival matters, state must be shared, and where it does not, the behaviour should be documented so that a failover test's outcome is expected.
The stateless form has no table and therefore no such problem, which is one of its genuine advantages and part of why it suits the controlled cases it fits.
A staged rollout
One client segment first, with a known population and people who can report problems usefully. The application inventory is built from what fails there. Then the segments whose applications are understood. The general population last, once the inventory is a list rather than a discovery process.
Reversing that order — general population first — produces a stream of individually small failures reported by people who cannot characterise them, which is a slow and unpleasant way to build the same inventory.
Blueprint framing
The CCIE Enterprise Infrastructure v1.1 blueprint covers IPv6 transition mechanisms within its infrastructure services domain. What is examined is generally the mechanism — how an address is synthesised, why the prefix must be routed to the translator, and the difference between the stateless and stateful forms — rather than a full deployment.
| Stage | Verify by | If it fails |
|---|---|---|
| Prefix routed inward | Route lookup from a client segment | Advertise it from the translator |
| Pool routed back | Route lookup upstream | Arrange it with whoever provides IPv4 |
| Translator works | Connect to a hand-computed address | Translator or routing, not the resolver |
| Resolver synthesises | Query it directly | Resolver configuration only |
| End to end | Connect by name | Both halves already proven, so it is the client |
| Applications | A staged rollout | The inventory, which is the real work |
Conclusion
The translator is the visible half and the name server is the half that makes it work. Asked for an IPv6 address for a name that has none, the resolver finds the IPv4 address and manufactures an IPv6 one around it, using a prefix that routing sends to the translator. The translator then recovers the IPv4 address by arithmetic from the low bits, which is why the destination direction needs no state even in the stateful form.
Stateful is what gets deployed. The stateless form maps one to one by arithmetic in both directions, which requires the IPv6 addressing plan to be derived from an IPv4 one and an IPv4 address per host — a strong constraint on a network whose point was to stop depending on IPv4 addressing. Stateful has the familiar trades of any overloaded translation: a table that can fill, no inbound connections without a mapping, and a failover that discards everything.
And everything that fails does so for one reason: something skipped the name lookup or asked for the wrong family. A hard-coded IPv4 address in a configuration file, an application requesting IPv4 specifically, a client validating the resolver's answers for itself and rejecting a manufactured one. None of these is fixed on the network. The deployment work in an IPv6-only project is the application inventory, and the single most useful diagnostic — connecting to a synthesised address computed by hand — separates the network half from the application half in about a minute. More CCIE Enterprise Infrastructure material — labs, protocol breakdowns and study guides — is collected on the SPOTO CCIE site.
External Links
- RFC 6146 — Stateful NAT64
- RFC 6147 — DNS64
- RFC 6052 — IPv6 Addressing of IPv4/IPv6 Translators
- RFC 7915 — IP/ICMP Translation Algorithm
- RFC 6877 — 464XLAT: Combination of Stateful and Stateless Translation
- RFC 7050 — Discovery of the IPv6 Prefix Used for Synthesis
- Cisco Learning Network — CCIE Enterprise Infrastructure
Reference Notes
- RFC 6146 specifies stateful NAT64, in which many IPv6 hosts are mapped onto a smaller pool of IPv4 addresses using transport port multiplexing.
- RFC 6146 requires that a stateful translator support hairpinning, so that two IPv6 hosts behind it can communicate through a translated address.
- RFC 6146 states that sessions must be initiated from the IPv6 side unless a static binding has been configured.
- RFC 6147 specifies DNS64, in which a resolver synthesises an AAAA record from an A record when no AAAA record exists for the queried name.
- RFC 6147 notes that synthesised records cannot carry a valid DNSSEC signature from the zone owner, and discusses the resulting interaction with validating clients.
- RFC 6052 defines the algorithmic embedding of an IPv4 address within an IPv6 address, including the permitted prefix lengths and the position of the embedded address for each.
- RFC 6052 reserves the well-known prefix 64:ff9b::/96 and restricts its use to translating to globally routable IPv4 addresses.
- RFC 7915 specifies the stateless IP and ICMP translation algorithm, including how headers are converted between the two families and which ICMP types have equivalents.
- RFC 7915 describes the handling of packet size differences between the families arising from the different header lengths and minimum MTU requirements.
- RFC 6877 specifies 464XLAT, in which a customer-side translator presents an IPv4 interface to applications and translates to IPv6 for transport across an IPv6-only network.
- RFC 7050 specifies a method by which a node discovers the IPv6 prefix used for synthesis by querying a well-known name that resolves only to IPv4 addresses.
- The CCIE Enterprise Infrastructure v1.1 unified exam topics include IPv6 transition mechanisms within the infrastructure services domain.