10.15. Addresses and PortsSince IPv4 is relatively simple compared to IPv6, let's cover the nameserver's IPv4 configuration together with IPv6. BIND 8.4.0 and later and all BIND 9 nameservers can use both IPv4 and IPv6 as a transport; that is, they can send and receive queries and responses over IPv4 and IPv6. Both nameservers also support similar substatements to configure which network interfaces and ports they listen on and send queries from. 10.15.1. Configuring the IPv4 TransportYou can specify which network interface your BIND 8 or BIND 9 nameserver listens on for queries using the listen-on substatement. In its simplest form, listen-on takes an address match list as an argument:
options {
listen-on { 192.249.249/24; };
};
The nameserver listens on any of the local host's network interfaces whose addresses match the address match list. To specify an alternate port (one other than 53) to listen on, use the port modifier:
options {
listen-on port 5353 { 192.249.249/24; };
};
In BIND 9, you can even specify a different port for each network interface:
options {
listen-on { 192.249.249.1 port 5353; 192.253.253.1 port 1053; };
};
Note that there's no way to configure most resolvers to query a nameserver on an alternate port, so this nameserver might not be as useful as you'd think. Still, it can serve zone transfers because you can specify an alternate port in a masters substatement:
zone "movie.edu" {
type slave;
masters port 5353 { 192.249.249.1; };
file "bak.movie.edu";
};
Or, if your BIND 9 nameserver has multiple master nameservers, each listening on a different port, you can use something like:
zone "movie.edu" {
type slave;
masters { 192.249.249.1 port 5353; 192.253.253.1 port 1053; };
file "bak.movie.edu";
};
BIND 9 even allows you to send your NOTIFY messages to alternate ports. To tell your master nameserver to notify all its slave nameservers on the same oddball port, use:
also-notify port 5353 { 192.249.249.9; 192.253.253.9; }; // zardoz's two addresses
To notify each on a different port, use:
also-notify { 192.249.249.9 port 5353; 192.249.249.1 port 1053; };
If your slave nameserver needs to use a particular local network interface to send queriesperhaps because one of its master nameservers recognizes it by only one of its many addressesuse the query-source substatement:
options {
query-source address 192.249.249.1;
};
Note that the argument isn't an address match list; it's a single IP address. You can also specify a particular source port to use for queries:
options {
query-source address 192.249.249.1 port 53;
};
BIND's default behavior is to use whichever network interface the route to the destination points out and a random, unprivileged port, i.e.:
options {
query-source address * port *;
};
Note that query-source applies only to UDP-based queries; TCP-based queries always choose the source address according to the routing table and use a random source port. There's an analogous transfer-source substatement that controls the source address to use for zone transfers. In BIND 9, it also applies to a slave nameserver's SOA queries and to forwarded dynamic updates:
options {
transfer-source 192.249.249.1;
};
As with query-source, the argument is just a single IP address, but with no address keyword. With BIND 8, there's no port modifier. With BIND 9, you can specify a source port:
options {
transfer-source 192.249.249.1 port 1053;
};
However, that source port applies only to UDP-based traffic (i.e., SOA queries and forwarded dynamic updates). transfer-source can also be used as a zone substatement, in which case it applies only to transfers (and, for BIND 9, SOA queries and dynamic updates) of that zone:
zone "movie.edu" {
type slave;
masters { 192.249.249.3; };
file "bak.movie.edu";
transfer-source 192.249.249.1; // always use IP address on same network
// for transfers of movie.edu
};
Finally, as of BIND 9.1.0, there's even a substatement that lets you control which address you send NOTIFY messages from, called notify-source. This comes in handy with multihomed nameservers because, by default, slaves accept only NOTIFY messages for a zone from IP addresses in that zone's masters substatement. notify-source's syntax is similar to the syntax of the other -source substatements; for example:
options {
notify-source 192.249.249.1;
};
As with transfer-source, notify-source can specify a source port and can be used as a zone statement to apply only to that zone:
zone "movie.edu" {
type slave;
masters { 192.249.249.3; };
file "bak.movie.edu";
notify-source 192.249.249.1 port 5353;
};
If you can't control the IP address from which NOTIFY messages are sent (because you don't administer the master server, for example), you can either include all the master's IP addresses in your zone's masters substatement, or you can use the allow-notify substatement to explicitly permit NOTIFY messages from addresses not listed in masters. 10.15.2. Configuring the IPv6 TransportBy default, a BIND 9 nameserver won't listen for IPv6-based queries. To configure it to listen on the local host's IPv6 network interfaces, use the listen-on-v6 substatement:
options {
listen-on-v6 { any; };
};
Before BIND 9.3.0, the listen-on-v6 substatement accepted only any and none as arguments. You can also configure a BIND nameserver to listen on an alternate portor even multiple portswith the port modifier:
options {
listen-on-v6 port 1053 { any; };
};
To listen on more than one IPv6 interface or port, use multiple listen-on-v6 substatements. The default port is, of course, 53. You can also determine which IPv6 address your nameserver uses as the source address for outgoing queries with the transfer-source-v6 substatement, as in:
options {
transfer-source-v6 222:10:2521:1:210:4bff:fe10:d24;
};
or, also specifying a source port:
options {
transfer-source-v6 222:10:2521:1:210:4bff:fe10:d24 port 53;
};
Only BIND 9 supports setting the source port, as in the second example. The default is to use the source address corresponding to whichever network interface the route points out and a random, unprivileged source port. As with transfer-source, you can use transfer-source-v6 as a zone substatement. And the source port applies only to SOA queries and forwarded dynamic updates. Finally, BIND 9.1.0 and later let you determine which IPv6 address to use in NOTIFY messages, à la the notify-source substatement. The IPv6 substatement is called, not surprisingly, notify-source-v6:
options {
notify-source-v6 222:10:2521:1:210:4bff:fe10:d24;
};
As with transfer-source-v6, you can specify a source port and use the substatement in a zone statement. 10.15.3. EDNS0UDP-based DNS messages have traditionally been limited to 512 bytes. This limit was instituted to prevent fragmentation, which in the early days of the Internet was costly and unreliable. Times have changed, though, and most paths on the Internet can accommodate much larger UDP datagrams. Thanks to new developments in DNS, such as DNSSEC and IPv6 support, the average response is getting larger. Responses from signed zones, in particular, can easily exceed the 512-byte limit, which can cause costly retries over TCP. The Extension Mechanisms for DNS, version 0, referred to as EDNS0, introduces a simple signaling system to DNS. Using this system, a resolver or nameserver can tell another nameserver that it can handle a DNS message larger than 512 bytes. (In fact, the sender can signal other capabilities, too, as we'll see in the next chapter.) BIND nameservers have supported EDNS0 since versions 9.0.0 and 8.3.0. These nameservers send EDNS0 signaling information by default, and try to negotiate a UDP-based DNS message size of 4,096 bytes. If they receive a response that indicates that the nameserver they're talking to doesn't understand EDNS0, they'll fall back to using messages that adhere to the old 512-byte limit. This technique generally works well, but occasionally you'll run across a nameserver that reacts badly to EDNS0 probes. To cope with these nameservers, you can use the new edns server substatement to turn off EDNS0 for that nameserver:
server 10.0.0.1 {
edns no;
};
This is supported in BIND 9.2.0 and later and BIND 8.3.2 and later nameservers. BIND 9.3.0 and later and 8.4.0 and later also allow you to configure the size of the UDP-based DNS messages your nameserver will negotiate with the edns-udp-size options substatment:
options {
directory "/var/named";
edns-udp-size 512;
};
This can be useful if your firewall doesn't understand that DNS messages can exceed 512 bytes in size and keeps dropping legitimate messages. (Of course, we think you should upgrade your firewall, but you may need to resort to this in the interim.) The maximum value for edns-udp-size is 4096; the minimum is 512. 10.15.4. IPv6 Forward and Reverse MappingClearly, the existing A record won't accommodate IPv6's 128-bit addresses; BIND expects an A record's record-specific data to be 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 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 it came up with a much more complicated one. This solution, which we'll describe shortly, involved the new A6 and DNAME records and required a complete overhaul of the BIND nameserver to implement. Then, after much acrimonious debate, the IETF decided that the new A6/DNAME scheme required too much overhead, was prone to failure, and was of unproven usefulness. At least temporarily, it 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. In the interest of preparing you for all possible futures, including one in which A6 and DNAME make a dramatic comeback, we'll cover both methods. 10.15.5. AAAA and ip6.arpaThe easy way to handle IPv6 forward mapping, described in RFC 1886, is with an address record that's four times as long as an A record. That's the AAAA (pronounced "quad A") record. The AAAA record takes as its record-specific data the textual format of an IPv6 address, as described earlier. So, for example, you'd see AAAA records like this one: ipv6-host IN AAAA 2001:db80:1:2:3:4:567:89ab RFC 1886 also established ip6.int, now replaced by ip6.arpa, a new reverse-mapping namespace 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 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.0.8.b.d.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. 10.15.6. A6, DNAMEs, Bitstring Labels, and ip6.arpaThat's the easy way. The more difficultand now only experimental way of handling IPv6 forward and reverse mapping uses two new record types, A6 and DNAME records. A6 and DNAME records are described in RFCs 2874 and 2672, respectively. Version 9.0.0 was the first version of BIND to support these records.
The main reason a replacement for the AAAA record and ip6.int reverse-mapping scheme was sought was because they make network renumbering difficult. For example, if an organization were to change ISPs, it would have to change all the AAAA records in its zone datafiles because some of the bits of an IPv6 address are an identifier for the ISP.[*] Or imagine an ISP changing address registries: this would wreak havoc with its customers' zone data.
10.15.6.1. A6 records and forward mappingTo make renumbering easier, A6 records can specify only a part of an IPv6 address, such as the last 64 bits (maybe the interface ID) assigned to a host's network interface, and then refer to the remainder of the address by a symbolic domain name. This allows zone administrators to specify only the part of the address under their control. To build an entire address, a resolver or nameserver must follow the chain of A6 records from a host's domain name to the address registry's ID. And that chain may branch if a site network is connected to multiple ISPs or if an ISP is connected to multiple address registries. For example, the A6 record: $ORIGIN movie.edu. drunkenmaster IN A6 64 ::0210:4bff:fe10:0d24 subnet1.v6.movie.edu. specifies the final 64 bits of drunkenmaster.movie.edu's IPv6 address (64 is the number of bits of the prefix not specified in this A6 record) and that the remaining 64 bits can be found by looking up an A6 record at subnet1.v6.movie.edu. subnet1.v6.movie.edu, in turn, specifies the last 16 bits of the 64-bit prefix (the subnet ID) that we didn't specify in drunkenmaster.movie.edu's A6 address, as well as the domain name of the next A6 record to look up: $ORIGIN v6.movie.edu. subnet1 IN A6 48 0:0:0:1:: movie-u.isp-a.net. subnet1 IN A6 48 0:0:0:1:: movie.isp-b.net. The first 48 bits of the prefix in subnet1.v6.movie.edu's record-specific data are set to 0 because they're not significant here. In fact, these records tell us to look up two A6 records next, one at movie-u.isp-a.net and one at movie.isp-b.net. That's because Movie U. has connections to two ISPs, ISP A and ISP B. In ISP A's zone, we might find: $ORIGIN isp-a.net. movie-u IN A6 40 0:0:21:: isp-a.rir-1.net. indicating an eight-bit pattern within the global routing prefix field set by ISP A for the Movie U. network. (Remember, the global routing prefix field can be hierarchical, too, comprising both an identifier for our ISP assigned to it by its address registry and our ISP's identifier for our network.) Since the ISP assigns some bits of the global routing prefix to us but has the rest of the prefix assigned by its address registry, we'd expect to see only our bits in our ISP's zone data. The remainder of the prefix appears in an A6 record in its address registry's zone. In ISP B's zone, we might find the following record showing us the bits that ISP assigns for our network: $ORIGIN isp-b.net. movie IN A6 40 0:0:42:: isp-b.rir-2.net. In the address registries' zones, we might find the next four bits of the IPv6 address: $ORIGIN rir-1.net. isp-a IN A6 36 0:0:0500:: rir-2.top-level-v6.net. and: $ORIGIN rir-2.net. isp-b IN A6 36 0:0:0600:: rir-1.top-level-v6.net. Finally, in the top-level IPv6 address registry's zone, we might find these records showing us the bits of the prefix assigned to RIR 1 and RIR 2: $ORIGIN top-level-v6.net. rir-1 IN A6 0 2001:db80::2 rir-2 IN A6 0 2001:db80::6 By following this chain of A6 records, a nameserver can assemble all 128 bits of drunkenmaster.movie.edu's two IPv6 addresses. These turn out to be: 2001:db80:2521:1:210:4bff:fe10:d24 2001:db80:6642:1:210:4bff:fe10:d24 The first of these uses a route through RIR 1 and ISP A to the Movie U. network, and the second uses a route through RIR 2 and ISP B. (We're connected to two ISPs for redundancy.) Note that if RIR 1 changes its prefix assignment for ISP A, it needs to change only the A6 record for isp-a.rir-1.net in its zone data; the change "cascades" into all A6 chains that go through ISP A. This makes the management of addressing on IPv6 networks very convenient and makes changing ISPs easy, too. You can probably already see some of the potential problems with A6 records. Resolving a domain name to a single IPv6 address may require several independent queries (to look up A6 records for an RIR's domain name, an ISP's domain name, and so on). Completing all of those queries may take many times longer than resolving a domain name's single AAAA record, and if any one of the "subresolutions" fails, the overall resolution process fails.
10.15.6.2. DNAME records and reverse mappingNow that you've seen how forward mapping works with A6 records, let's look at how reverse-mapping IPv6 addresses works. As with A6 records, unfortunately, this isn't nearly as simple as ip6.arpa. Reverse-mapping IPv6 addresses involves DNAME records, described in RFC 2672, and bitstring labels, introduced in RFC 2673. DNAME records are a little like wildcard CNAME records. They're used to substitute one suffix of a domain name with another. For example, if we previously used the domain name movieu.edu at Movie U. but have since changed to movie.edu, we can replace the old movieu.edu zone with this one:
$TTL 1d
@ IN SOA toystory.movie.edu. root.movie.edu. (
2000102300
3h
30m
30d
1h )
IN NS toystory.movie.edu.
IN NS wormhole.movie.edu.
IN MX 10 postmanrings2x.movie.edu.
IN DNAME movie.edu.
The DNAME record in the movieu.edu zone applies to any domain name that ends in movieu.edu except movieu.edu itself. Unlike the CNAME record, the DNAME record can coexist with other record types owned by the same domain name as long as they aren't CNAME or other DNAME records. The owner of the DNAME record may not have any subdomains, though. When the movieu.edu nameserver receives a query for any domain name that ends in movieu.edu, say cuckoosnest.movieu.edu, the DNAME record tells it to "synthesize" an alias from cuckoosnest.movieu.edu to cuckoosnest.movie.edu, replacing movieu.edu with movie.edu: cuckoosnest.movieu.edu. IN CNAME cuckoosnest.movie.edu. It's a little like sed's "s" (substitute) command. The movieu.edu nameserver replies with this CNAME record. If it's responding to a newer nameserver, it also sends the DNAME record in the response, and the recipient nameserver can then synthesize its own CNAME records from the cached DNAME. Bitstring labels are the other half of the magic involved in IPv6 reverse mapping. Bitstring labels are simply a compact way to represent a long sequence of binary (i.e., one-bit) labels in a domain name. Say you want to permit delegation between any two bits of an IP address. This might compel you to represent each bit of the address as a label in a domain name. But that would require over 128 labels for a domain name that represented an IPv6 address! Oy! That exceeds the limit on the number of labels in a normal domain name! Bitstring labels concatenate the bits in successive labels into a shorter hexadecimal, octal, binary, or dotted-octet string. The string is encapsulated between the tokens "\[" and "]" to distinguish it from a traditional label, and begins with one letter that determines the base of the string: b for binary, o for octal, and x for hexadecimal. Here are the bitstring labels that correspond to drunkenmaster.movie.edu's two IPv6 addresses: \[x2001db802521000102104bfffe100d24] \[x2001db806642000102104bfffe100d24] Notice that the most significant bit begins the string, as in the text representation of an IPv6 address, but in the opposite order of the labels in the in-addr.arpa domain. Despite this, these two bitstring labels are simply a different encoding of traditional domain names that begin: 0.0.1.0.0.1.0.0.1.0.1.1.0.0.0.0.0.0.0.0.1.0.0.0.0.1.1.1.1.1.1.1... Also note that all 32 hex digits in the address are present; you can't drop leading zeros, because there are no colons to separate groups of four digits. Bitstring labels can also represent parts of IPv6 addresses, in which case you need to specify the number of significant bits in the string, separated from the string by a slash. So RIR 1's portion of the global routing prefix is \[x2001db802/36]. Together, DNAMEs and bitstring labels are used to match portions of a long domain name that encode an IPv6 address and to iteratively change the domain name looked up to a domain name in a zone under the control of the organization that manages the host with that IPv6 address. Imagine we're reverse-mapping \[x2001db806642000102104bfffe100d24].ip6.arpa, the domain name that corresponds to drunkenmaster.movie.edu's network interface (when reached through RIR 2 and ISP B). The root nameservers would probably refer our nameserver to the ip6.arpa nameservers, which contain these records: $ORIGIN ip6.arpa. \[x2001db802/36] IN DNAME ip6.rir-1.net. \[x2001db806/36] IN DNAME ip6.rir-2.net. The second of these matches the beginning of the domain name we're looking up, so the ip6.arpa nameservers reply to our nameserver with an alias that says: \[x2001db806642000102104bfffe100d24].ip6.arpa. IN CNAME \[x642000102104bfffe100d24].ip6.rir-2.net. Notice that the first nine hex digits (the most significant 36 bits) of the address are stripped off, and the end of the target of the alias is now ip6.rir-2.net, since we know this address belongs to RIR 2. In ip6.rir-2.net, we find: $ORIGIN ip6.rir-2.net. \[x6/4] IN DNAME ip6.isp-b.net. This turns the domain name in our new query: \[x642000102104bfffe100d24].ip6.rir-2.net into: \[x42000102104bfffe100d24].ip6.isp-b.net Next, our nameserver queries the ip6.isp-b.net nameservers for the new domain name. This record in the ip6.isp-b.net zone: $ORIGIN ip6.isp-b.net. \[x42/8] IN DNAME ip6.movie.edu. turns the domain name we're looking up into: \[x000102104bfffe100d24].ip6.movie.edu The ip6.movie.edu zone, finally, contains the PTR record that gives us the domain name of the host we're after: $ORIGIN ip6.movie.edu. \[x000102104bfffe100d24/80] IN PTR drunkenmaster.ip6.movie.edu. (Though we could have used another DNAME just for subnet1, we didn't.) Mercifully, as a zone administrator you'll probably only be responsible for maintaining PTR records like the ones in ip6.movie.edu. Even if you work for an RIR or ISP, creating DNAME records that extract the appropriate bits of the global routing prefix from your customers' addresses isn't too tough. And you gain the convenience of using a single zone datafile for your reverse-mapping information, even though each of your hosts has multiple addresses and can switch ISPs without changing all of your zone datafiles. |