Chapter 4. DNS64

During the (likely very long) transition from IPv4 to IPv6, ISPs and other organizations will implement new networks that only support IPv6. For the foreseeable future, though, clients on those networks will still need access to services (e.g., websites) that don’t yet support IPv6. NAT64 and DNS64[3] are a pair of complementary transition technologies that help provide that access.

NAT64 is a function run on a dual-stack host. A NAT64 server accepts connections from clients that only speak IPv6 and then uses its own IPv4 connectivity to communicate with IPv4-only servers on those clients’ behalf, then copies data between the IPv4 and IPv6 connections, effectively “bridging” the IPv4 and IPv6 networks. The clients don’t actually realize they’re connecting through NAT64—they’re led to believe that the IPv4-only servers they want to communicate with support IPv6 and that they’re talking directly to them.

How is that misdirection achieved? Through DNS—DNS64, in particular. The IPv6-only clients are configured to use one or more special name servers that support the DNS64 function. When one of these name servers receives a query from a client for AAAA (IPv6 address) records for some domain name, it looks for an answer, as it normally would. If it doesn’t find any such records, it tries looking up A records for the same domain name. If it finds one or more A records, it doesn’t return them to the client (which can’t use them, anyway, and wouldn’t accept them, since it asked specifically for AAAA records). It “synthesizes” an equal number of AAAA records from those A records, embedding the 32-bit IPv4 addresses in 128-bit IPv6 addresses. Now the client believes the server supports IPv6 and that it can communicate with it directly.

The client, then, tries to connect to one of these fictional—er, synthesized—IPv6 addresses. How does the NAT64 server intercept this traffic? Easy! The route to the network on which the synthesized IPv6 address lies leads right to the NAT64 server. The NAT64 server terminates the IPv6 connection, extracts the embedded IPv4 address, and connects to the IPv4 server on the IPv6 client’s behalf. This process is illustrated in Figure 4-1.

DNS64 and NAT64 at Work
Figure 4-1. DNS64 and NAT64 at Work

BIND versions 9.8.0 and later support DNS64 with the dns64 options substatement. dns64 supports the configuration of an IPv6 prefix to which the embedded IPv4 address is appended, as well as an optional suffix that is then appended to the IPv4 address to complete the 128-bit address. (The prefix is often 96 bits long, in which case no suffix is required, or even possible.) Here’s a basic example:

dns64 64:ff9b::/96 {
    suffix ::;
};

::, an all-zeroes suffix, is the default, so you can leave that substatement out if you like.

Now, there are good reasons that you may not want to apply DNS64 to every querier. For instance, you may have a community of dual-stack clients on your network. When asked by an application to find the address of a server, many stub resolvers on dual-stack clients will send AAAA queries before they send A queries. With DNS64 enabled, such clients would never see the A records of IPv4-only servers; DNS64 would always return synthesized AAAA records to them, even though the clients were perfectly capable of using the servers’ A records. This, in turn, would shunt traffic through your NAT64 infrastructure unnecessarily.

The dns64 statement supports a clients substatement that allows you to select which clients the DNS64 function applies to. By default, DNS64 applies to all clients; that is:

dns64 64:ff9b::/96 {
    clients { any; };
};

But you can specify any ACL you like as an argument. Here’s an example:

dns64 64:ff9b::/96 {
    clients { 2001:db8:cafe:1::/64; };
};

As always, it’s a good idea to use named ACLs whenever possible for clarity.

There are also IPv4 networks that you may not want mapped into IPv6 addresses by DNS64. For example, if you run a DNS64 function to give your IPv6-only clients access to the IPv4 Internet, you don’t want to embed any RFC 1918 addresses that name servers on the Internet might inadvertently return. To avoid that, use the dns64 mapped substatement. This dns64 statement would prevent DNS64 from mapping 10/8 addresses, for example:

dns64 64:ff9b://96 {
    mapped { !10/8; any; };
};

Of course, RFC 1918 includes more than just 10/8.

Note

You may notice that I use the prefix 64:ff9b:://96 liberally in my DNS64 examples. That’s because that network is reserved for mapping IPv4 addresses into IPv6, and it’s the default used by many NAT64 implementations. You can use a different prefix if you prefer, but make sure it matches what’s configured on (and routed to) your NAT64 server, and choose it from some private IPv6 address space (there’s plenty of it) so it doesn’t interfere with routing to real IPv6 destinations. NAT64 prefixes are restricted by RFC to /32s, /40s, /48s, /56s, /64s, or /96s. If you choose a /96, a suffix is superfluous, of course, but other prefix lengths allow the configuration of a suffix (though again, the suffix is optional, and defaults to ::). As with the prefix, make sure your NAT64 server is configured with the same suffix.

Normally, DNS64 only applies to domain names that don’t have AAAA records. (If the domain name had one or more AAAA records, the name server would simply have returned them to the IPv6-only client.) But sometimes you may want the name server to ignore AAAA records that contain certain IPv6 addresses and apply DNS64 to a domain name. In that case, you can use the exclude substatement, which allows you to specify one or more IPv6 networks or addresses whose presence DNS64 should ignore and synthesize new AAAA records anyway. Here’s an example:

dns64 64:ff9b::/96 {
    clients { 2001:db8:cafe:1::/64; };
    mapped { !10/8; any; };
    exclude { 64:ff9b::/96; };
};

This tells DNS64 to ignore any AAAA records that map to IPv6 addresses on the network 64:ff9b::/96 and to look up A records for those domain names and synthesize new AAAA records instead.

Authoritative Name Servers and DNS64

What I’ve described so far is DNS64 as performed by a recursive name server, but authoritative name servers can implement DNS64, too. In fact, if you configure your name server to do DNS64 and it’s also authoritative for one or more zones, it’ll apply DNS64 to queries in those zones by default, too. In this case, the name server synthesizes AAAA records from A records in zones for which it’s authoritative. (Of course, it’ll only do this if no AAAA records exist for the domain name.)

If you want to restrict DNS64 to recursive queries, you can use the recursive-only substatement:

dns64 64:ff9b::/96 {
    recursive-only yes;
};

The default is to apply DNS64 to both recursive and nonrecursive queries.

Interaction Between DNS64 and DNSSEC

After reading about DNS64, those of you who have already read DNS and BIND’s “Security” chapter may object: doesn’t the mechanism, when it’s working as designed, break DNSSEC? Yes, it sure can.

Imagine that a monolingual IPv6 client queries a recursive name server that supports DNS64 for AAAA records attached to a domain name in a signed zone. The recursive name server looks up AAAA records for the domain name and finds none. If the recursive name server is configured to perform DNSSEC validation and has a valid chain of trust to the zone in question, it will cryptographically validate the negative response from the authoritative name server. Surely it can’t lie to the client about an answer it has validated?

Actually, it can, and in many cases, the client won’t notice at all. That’s because most clients don’t perform validation themselves, but rely entirely on their recursive name servers for that.

As a safeguard, however, a BIND name server doesn’t synthesize a AAAA response if the DNSSEC OK (DO) flag was set in the query. In this case, the client querying the name server could be another name server configured to use it as a forwarder, and it might be configured to perform validation. That validation would fail on any synthesized AAAA record.

If you’re really hell-bent on rewriting even those responses, you can use the break-dnssec substatement:

dns64 64:ff9b://96 {
    break-dnssec yes;
};

DNS64 and Reverse Mapping

There’s one last detail of DNS64 worth mentioning: reverse mapping. If a client using a name server configured to perform DNS64 tries to reverse-map a synthesized IPv6 address, what happens? The name server in question responds with a CNAME record pointing the domain name used to reverse-map the synthesized IPv6 address (the one under ip6.arpa) to the domain name corresponding to the embedded IPv4 address (under in-addr.arpa). So if an A record pointing to 192.168.0.1 synthesizes a AAAA record pointing to 64:ff9b::192.168.0.1 (or 64:ff9b::c0a8:1—same thing), the CNAME record looks like this:

1.0.0.0.8.a.0.c.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.b.9.f.f.6.4.0.0.ip6.arpa.    CNAME
1.0.168.192.in-addr.arpa.

The result is exactly what you’d want: the synthesized IPv6 address reverse-maps to whichever domain name the embedded IPv4 address maps to!



[3] NAT64 and DNS64 are pronounced as “NAT six four” and “DNS six four,” respectively—not “NAT sixty-four” and “DNS sixty-four.”

Get DNS and BIND on IPv6 now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.