Chapter 1. DNS and IPv6

Background

In early February 2011, the Internet Assigned Numbers Authority, or IANA, assigned the last remaining IPv4 address space to the five Regional Internet Registries (RIRs). As of this writing, the RIRs haven’t yet doled out that address space to carriers and other customers, but it’s clear that the exhaustion of IPv4 address space is imminent.

For most organizations on the Internet, the depletion of the Internet’s unallocated IPv4 address space won’t necessitate immediate changes—IPv4 isn’t going anywhere for the foreseeable future. In certain exceptional cases, however, organizations may need to implement IPv6 almost right away: mobile carriers and ISPs seeking to expand their subscriber bases, for example, may need to use IPv6 for new subscribers if they lack additional IPv4 address space to use for expansion.

The Internet’s transition from IPv4 to IPv6 has begun. With the US government’s mandate that government agencies move their networks to IPv6, a growing number of users will access the Internet over the new protocol, and an increasing number of resources—websites, name servers, mail servers, and more—will be accessible via IPv6. In some cases, some may only be accessible over IPv6.

The transition to IPv6 will take years, maybe decades, to complete. Today, of course, IPv6 is already routed over the Internet: 9% of the Internet’s Autonomous Systems advertise routes to both IPv4 and IPv6 networks. But IPv6 constitutes a tiny fraction of the traffic routed over the Internet. Organizations deploying new IPv6 networks today need to implement transition technologies that enable their IPv6-based devices to reach IPv4-only services.

Over time, however, the balance will shift, and so will the responsibility. As IPv6 becomes the predominant protocol on the Internet, the remaining pockets of IPv4 will need to accommodate IPv6, not vice versa. I imagine the transition playing out something like the move from rotary dialing to Touch-Tone™; in 1963, when the switch began, Touch-Tone™ was a novelty you had to pay extra for. Now, of course, Touch-Tone™ is the norm (unless you’ve already moved on to VoIP) and rotary dialing is a curiosity you have to pay your phone company more to accommodate—if they can still handle it at all.

IPv6 and DNS

The exhaustion of the IPv4 address space wasn’t unexpected, of course. The Internet Engineering Task Force (IETF) developed IP version 6 in the 1990s largely in anticipation of this day. Likewise, the Domain Name System was extended to accommodate IPv6’s longer IP addresses by adding new record types, and new versions of name servers, including BIND, were released to support those new record types as well as the use of IPv6 to transport queries and responses. At this point, all but ancient BIND name servers support IPv6, though in most cases that support isn’t configured or used. We’ve just been waiting patiently for the protocol to catch on!

The ABCs of IPv6 Addresses

The most widely known aspect of IPv6, and really the only one that matters to DNS, is the length of the IPv6 address: 128 bits, four times as long as IPv4’s 32-bit address. The preferred representation of an IPv6 address is eight groups of as many as four hexadecimal digits, separated by colons. For example:

2001:0db8:0123:4567:89ab:cdef:0123:4567

The first group, or quartet, of hex digits (2001, in this example) represents the most significant (or highest-order) sixteen bits of the address. In binary terms, 2001 is equivalent to 0010000000000001.

Groups of digits that begin with one or more zeros don’t need to be padded to four places, so you can also write the previous address as:

2001:db8:123:4567:89ab:cdef:123:4567

Each group must contain at least one digit, though, unless you’re using the :: notation. The :: notation allows you to compress sequential groups of zeros. This comes in handy when you’re specifying just an IPv6 prefix. For example:

2001:db8:dead:beef::

specifies the first 64 bits of an IPv6 address as 2001:db8:dead:beef and the remaining 64 as zeros.

You can also use :: at the beginning of an IPv6 address to specify a suffix. For example, the IPv6 loopback address is commonly written as:

::1

or 127 bits of zero followed by a single one bit. You can even use :: in the middle of an address as shorthand for contiguous groups of zeros:

2001:db8:dead:beef::1

You can use the :: shorthand only once in an address, since more than one would be ambiguous.

IPv6 prefixes are specified in a format similar to IPv4’s CIDR notation. As many bits of the prefix as are significant are expressed in the standard IPv6 notation, followed by a slash and a decimal count of exactly how many significant bits there are. So the following four prefix specifications are equivalent (though obviously not equivalently terse):

2001:db8:dead:beef:0000:00f1:0000:0000/96
2001:db8:dead:beef:0:f1:0:0/96
2001:db8:dead:beef::f1:0:0/96
2001:db8:dead:beef:0:f1::/96

IPv6 is similar to IPv4 in that it supports variable-length network masks, and addresses are divided into network and host portions. However, in IPv6, there are recommended network masks for networks and subnets: the first 48 bits of an IPv6 address should identify a particular end site and a 64-bit prefix should identify one of up to 65,536 subnetworks at the site identified by the “parent” 48-bit prefix. As of this writing, all global unicast IPv6 addresses on the Internet (addresses that are unique and globally routable) have prefixes that begin with the binary value 001 (equivalent to 2000::/3). These are assigned by Regional Internet Registries (RIRs) and Internet service providers. The prefix itself may be hierarchical, with an RIR responsible for allocating higher-order bits to various ISPs, and ISPs responsible for allocating the lowest-order bits of the prefix to its customers.

After the end-site prefix, unicast IPv6 addresses typically contain another 16 bits that identify the particular subnetwork within an end site, called the subnet ID. The remaining bits of the address identify a particular network interface and are referred to as the interface ID.

Here’s a diagram that shows how these parts fit together:

|        48 bits         |  16 bits  |           64 bits          |
+------------------------+-----------+----------------------------+
|         prefix         | subnet ID |       interface ID         |
+------------------------+-----------+----------------------------+
/                        \
|                         +------------------------------------\
|  3bits   |  9bits   |  12-20bits   |        16-24bits         |
+----------+----------+--------------+--------------------------+
|  IETF    |   IANA   |      RIR     |         RIR or ISP       |
+----------+----------+--------------+--------------------------+

As you can see in the diagram, the 48-bit prefix is made up of several parts. As previously mentioned, the first three bits are assigned by IETF to indicate “Global Unicast Space.” The next nine bits are assigned by IANA to a particular RIR (for example, 2620::/12 is assigned to ARIN, the American Registry for Internet Numbers). The RIR then assigns prefixes to ISPs and end users ranging from 24 to 48 bits (the RIR controls between 12 and 36 bits). Finally, in an ISP’s address space, the ISP can assign the bits after its RIR-assigned prefix up to the /48 allocated to each customer end site.

Coincidentally, Movie University just arranged to get IPv6 connectivity from our ISP. The ISP assigned us a /48-sized IPv6 network, 2001:db8:cafe::/48, which we’ll subnet using the scheme just described into /64-sized subnetworks.

Note

What’s this fe80:: address?

If you’re poking around on a Unix or Linux system with ifconfig, netstat or the like, you may notice that your host’s network interfaces already have IPv6 addresses assigned to them, starting with the quartet “fe80.” These are link-local scoped addresses, derived automatically from the interfaces’ hardware addresses. The link-local scope is significant—you can’t access these addresses from anywhere but the local subnet, so don’t use them in delegation, masters substatements, and the like. Use global unicast addresses assigned to the host instead. You probably shouldn’t even use link-local addresses in the configuration of resolvers on the same subnet if there’s any chance that those resolvers will move (e.g., if they’re on laptops or other mobile devices).

IPv6 Forward and Reverse Mapping

Clearly, DNS’s A record won’t accommodate IPv6’s 128-bit addresses; an A record’s record-specific data is a 32-bit address in dotted-octet format.

The IETF came up with a simple solution to this problem, described in RFC 1886. A new type of address record, AAAA, was used to store a 128-bit IPv6 address, and a new IPv6 reverse-mapping domain, ip6.int, was introduced. This solution was straightforward enough to implement in BIND 4. Unfortunately, not everyone liked the simple solution, so they came up with a much more complicated one. This solution introduced the new A6 and DNAME records and required a complete overhaul of the BIND name server to implement. Then, after much acrimonious debate, the IETF decided that the new A6/DNAME scheme involved too much overhead, was prone to failure, and was of unproven usefulness. At least temporarily, they moved the RFC that describes A6 records off the IETF standards track to experimental status, deprecated the use of DNAME records in reverse-mapping zones, and trotted old RFC 1886 back out. Everything old is new again.

For now, the AAAA record is the way to handle IPv6 forward mapping. The use of ip6.int is deprecated, however, mostly for political reasons; it’s been replaced by ip6.arpa.

AAAA and ip6.arpa

The AAAA (pronounced “quad A,” not “ahh!”) record, described in RFC 1886, is a simple address record with record-specific data that’s four times as long as an A record, hence the four As in the record type. The AAAA record takes as its record-specific data the textual format of an IPv6 address, exactly as described earlier. So for example, you’d see AAAA records like this one:

ipv6-host    IN    AAAA    2001:db8:1:2:3:4:567:89ab

As you can see, it’s perfectly okay to use shortcuts in the IPv6 address, including dropping leading zeroes from quartets and replacing one or more contiguous quartets of all zeroes with ::.

RFC 1886 also established ip6.int, now replaced by ip6.arpa, a new reverse-mapping name space for IPv6 addresses. Each level of subdomain under ip6.arpa represents four bits of the 128-bit address, encoded as a hexadecimal digit just like in the record-specific data of the AAAA record. The least significant (lowest-order) bits appear at the far left of the domain name. Unlike the format of IPv6 addresses in AAAA records, omitting leading zeros is not allowed, so there are always 32 hexadecimal digits and 32 levels of subdomain below ip6.arpa in a domain name corresponding to a full IPv6 address. The domain name that corresponds to the address in the previous example is:

b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.

These domain names have PTR records attached, just as the domain names under in-addr.arpa do:

b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.8.b.d.1.0.0.2.ip6.arpa.  IN  PTR  
mash.ip6.movie.edu.

Adding AAAA Records to Forward-Mapping Zones

A and AAAA records can coexist side-by-side in any forward-mapping zone. So, for example, if your host has both an IPv4 and an IPv6 address (commonly called a “dual-stack” host), you can attach both A and AAAA records to its domain name:

suckerpunch    IN    A    192.249.249.111
               IN    AAAA 2001:db8:cafe:f9::d3

However, you should be careful with that configuration, at least for the time being. Some current resolvers will always look up AAAA records before A records, even if the host running the resolver lacks the ability to communicate with all IPv6 addresses (for example, the host only has a link-local IPv6 address, or uses some transition technology that gives it limited IPv6 connectivity). If you attach both A and AAAA records to a single domain name, as in the example above, a user of one of these broken resolvers would need to wait for his connection to the IPv6 address to time out before successfully connecting to the IPv4 address, which could take as long as a few minutes (see in Chapter 2 for a mechanism to help you deal with this).

Until these broken resolvers are fixed, it’s prudent to attach A and AAAA records to different domain names, at least for hosts offering services:

suckerpunch        IN    A    192.249.249.111
suckerpunch-v6     IN    AAAA 2001:db8:cafe:f9::d3

If you like the aesthetics better, you can use “v6” as a label in the domain name instead of as a suffix to the hostname:

suckerpunch.v6     IN    AAAA 2001:db8:cafe:f9::d3

Note that this doesn’t require that you create a new subzone called v6.movie.edu; a subdomain in the same zone will do nicely.

IPv6 Reverse-Mapping Zones

If you use the standard IPv6 subnetting scheme shown in the diagram in , the reverse-mapping zones that correspond to your subnets will have 18 labels. For example, the subnet that suckerpunch.v6.movie.edu is on, 2001:db8:cafe:f9::/64, would correspond to the reverse-mapping zone 9.f.0.0.e.f.a.c.8.b.d.0.1.0.0.2.ip6.arpa. Remember that DNS is case-insensitive, so we could also have called the zone 9.F.0.0.E.F.A.C.8.B.D.0.1.0.0.2.IP6.ARPA or even 9.F.0.0.e.F.a.C.8.b.D.0.1.0.0.2.iP6.aRpA, if we’d been feeling punchy. They all would have handled reverse mapping of IPv6 addresses just as well.

As with IPv4 reverse-mapping zones, IPv6 reverse-mapping zones mostly contain PTR records. And as with any zone, they must contain one SOA record and one or more NS records. Here’s what the beginning of that zone looks like:

$TTL 1d
@    IN    SOA    terminator.movie.edu.    hostmaster.movie.edu.    (
    2011030800        ; Serial number
    1h                ; Refresh (1 hour)
    15m               ; Retry (15 minutes)
    30d               ; Expire (30 days)
    10m )             ; Negative-caching TTL (10 minutes)

    IN    NS    terminator.movie.edu.
    IN    NS    wormhole.movie.edu.

3.d.0.0.0.0.0.0.0.0.0.0.0.0.0.0    PTR    suckerpunch.v6.movie.edu.
4.d.0.0.0.0.0.0.0.0.0.0.0.0.0.0    PTR    super8.v6.movie.edu.

Here’s hoping that most of your hosts will use dynamic update to register their own AAAA and PTR records, or else you’re going to wear out the period key on your keyboard.

If you’re going to add a lot of PTR records to an IPv6 reverse-mapping zone by hand, it’s a good idea to make liberal use of the $ORIGIN control statement. For example, you could rewrite those last two PTR records as:

$ORIGIN 0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.f.0.0.e.f.a.c.8.b.d.0.1.0.0.2.ip6.arpa.
3.d        PTR    suckerpunch.v6.movie.edu.
4.d        PTR    super8.v6.movie.edu.

The zone statement we added to the named.conf file on terminator to configure it as the primary name server for the reverse-mapping zone looks like this:

zone "9.f.0.0.e.f.a.c.8.b.d.0.1.0.0.2.ip6.arpa" {
    type master;
    file "db.2001:db8:cafe:f9";
};

Of course, you can name the zone data file whatever you like, but I suggest embedding the subnet’s prefix in there somewhere.

Warning

It’s probably best to avoid the use of the $GENERATE control statement in IPv6 reverse-mapping zones. Figuring out the right syntax to use to generate PTR records for such zones is tricky, and it’s easy to create so many PTR records that you can cause your name server to run out of memory.

Delegation and Reverse-Mapping Zones

You handle delegation with IPv6 reverse-mapping zones just as you would with IPv4 reverse-mapping zones—except it’s easier in one important respect. Those of you unfortunate enough to employ IPv4 subnet masks that don’t end on an octet boundary (e.g. /8, /16, and /24) wind up with either more than one reverse-mapping zone per subnet or multiple subnets per reverse-mapping zone. Those of you with subnets smaller than a /24 may even be forced to follow RFC 2317, which is really unfortunate.

With IPv6’s standard subnetting scheme, each subnet can contain a whopping 264 addresses, and you usually get over 65,000 subnets (assuming your ISP or RIR assigns a full /48 to you). Consequently, you probably won’t find yourself tempted to try to use a non-aligned subnet mask to make a subnet just large enough to accommodate the connected hosts. You’ll create a /48-sized reverse-mapping zone for your entire IPv6 network, and if necessary can delegate /64-sized subdomains from it.

For Movie University’s /48, 2001:db8:cafe::/48, the corresponding reverse-mapping zone is e.f.a.c.8.b.d.0.1.0.0.2.ip6.arpa. If we needed to delegate the 2001:db8:cafe:f9::/64 subnet, introduced earlier, to a different set of name servers, we could add delegation like so:

$TTL 1d
@    IN    SOA    terminator.movie.edu.    hostmaster.movie.edu.    (
    2011030800        ; Serial number
    1h                ; Refresh (1 hour)
    15m               ; Retry (15 minutes)
    30d               ; Expire (30 days)
    10m )             ; Negative-caching TTL (10 minutes)

    IN    NS    terminator.movie.edu.
    IN    NS    wormhole.movie.edu.

9.f.0.0    IN    NS    adjustmentbureau.movie.edu.
           IN    NS    rango.movie.edu.

Of course, no glue addresses are necessary, because the domain names of the name servers aren’t below the delegation point.

Built-In Empty Reverse-Mapping Zones

There are quite a few IPv6 addresses and networks that serve special purposes. For example, IPv6, like IPv4, has an unspecified address (used by uninitialized network interfaces) and a loopback address, as well as networks for link-local addresses and more. The latest versions of BIND 9 include built-in empty versions of the reverse-mapping zones that correspond to these addresses and networks. The zones are empty so that your local BIND name server will respond to any queries to reverse map these addresses immediately with a negative answer, without forwarding that query off to the Internet to another name server just to get the same negative answer or no answer at all.

The table below lists the built-in reverse-mapping zones, the functions of the addresses and networks they map to, and the rough equivalent in IPv4:

Reverse-mapping Zone Name

Function

IPv4 Equivalent

0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa

Unspecified IPv6 address

0.0.0.0

1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa

IPv6 Loopback Address

127.0.0.1

8.b.d.0.1.0.0.2.ip6.arpa

IPv6 Documentation Network

192.0.2/24

d.f.ip6.arpa

Unique Local Addresses

10/8, etc. (RFC 1918)

8.e.f.ip6.arpa

Link-Local Addresses

169.254/16

9.e.f.ip6.arpa

Link-Local Addresses

169.254/16

a.e.f.ip6.arpa

Link-Local Addresses

169.254/16

b.e.f.ip6.arpa

Link-Local Addresses

169.254/16

BIND is smart enough to notice if you’ve already configured your own version of one of these reverse-mapping zones (even if the zone isn’t an authoritative zone, such as a forward or stub zone), so you can easily override BIND’s empty zones. To disable individual built-in empty zones without creating explicit zone statements for them, use the disable-empty-zone substatement, which takes as an argument the domain name of the zone to disable:

options {
    disable-empty-zone "d.f.ip6.arpa";
};

To disable all built-in empty zones, you can use the empty-zones-enable substatement. By default, of course, they’re enabled, so

options {
    empty-zones-enable no;
};

will disable them. You can use disable-empty-zone and empty-zones-enable as either options or view substatements.

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

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.