"Only in the usual way," Alice said, smiling.
"That's hardly enough," he said, anxiously. "You see the wind is so very strong here. It's as strong as soup."
"Have you invented a plan for keeping the hair from being blown off?" Alice enquired.
"Not yet," said the Knight. "But I've got a plan for keeping it from falling off."
Why should you care about DNS security? Why go to the trouble of securing a service that mostly maps names to addresses? Let us tell you a story.
In July 1997, during two periods of several days, users around the Internet who typed www.internic.net into their web browsers thinking they were going to the InterNIC's web site instead ended up at a web site belonging to the AlterNIC. (The AlterNIC runs an alternate set of root name servers that delegate to additional top-level domains with names like med and porn.) How'd it happen? Eugene Kashpureff, then affiliated with the AlterNIC, had run a program to "poison" the caches of major name servers around the world, making them believe that www.internic.net's address was actually the address of the AlterNIC web server.
Kashpureff hadn't made any attempt to disguise what he had done; the web site that users reached was plainly the AlterNIC's, not the InterNIC's. But imagine someone poisoning your name server's cache to direct www.amazon.com or www.wellsfargo.com to his own web server, conveniently well outside local law enforcement jurisdiction. Further, imagine your users typing in their credit card numbers and expiration dates. Now you get the idea.
Protecting your users against these kinds of attacks requires DNS security. DNS security comes in several flavors. You can secure transactions -- the queries, responses, and other messages your name server sends and receives. You can secure your name server, refusing queries, zone transfer requests, and dynamic updates from unauthorized addresses, for example. You can even secure zone data by digitally signing it.
Since DNS security is one of the most complicated topics in DNS, we'll start you off easy and build up to the hard stuff.
TSIG, now codified in RFC 2845, is relatively simple to configure, lightweight for resolvers and name servers to use, and flexible enough to secure DNS messages (including zone transfers) and dynamic updates. (Contrast this with the DNS Security Extensions, which we'll discuss at the end of this chapter.)
With TSIG configured, a name server or updater adds a TSIG record to the additional data section of a DNS message. The TSIG record "signs" the DNS message, proving that the message's sender had a cryptographic key shared with the receiver and that the message wasn't modified after it left the sender.[81]
[81]Cryptography wonks may argue that TSIG "signatures" aren't really signatures in a cryptographic sense because they don't provide nonrepudiation. Since either holder of the shared key can create a signed message, the recipient of a signed message can't claim that only the sender could have sent it (the recipient could have forged it himself).
TSIG uses a one-way hash function called MD5. In particular, it uses a variant of MD5 called HMAC-MD5. HMAC-MD5 works in a keyed mode in which the 128-bit hash value depends not only on the input, but also on a key.
You should know, however, that the TSIG record includes a hash value computed over the entire DNS message as well as some additional fields. (When we say "computed over," we mean that the raw, binary DNS message and the additional fields are fed through the HMAC-MD5 algorithm to produce the hash value.) The hash value is keyed with a secret shared between the signer and the verifier. Verifying the hash value proves both that the DNS message was signed by a holder of the shared secret and that it wasn't modified after it was signed.
The additional fields in the TSIG record include the time the DNS message was signed. This helps combat replay attacks, in which a hacker captures a signed, authorized transaction (say a dynamic update deleting an important resource record) and replays it later. The recipient of a signed DNS message checks the time signed to make sure it's within the allowable "fudge" (another field in the TSIG record).
The argument to the key statement in this example, terminator-wormhole.movie.edu, is actually the name of the key, though it looks like a domain name. (It's encoded in the DNS message in the same format as a domain name.) The TSIG RFC suggests you name the key after the two hosts that use it. The RFC also suggests that you use different keys for each pair of hosts.key terminator-wormhole.movie.edu. { algorithm hmac-md5; secret "skrKc4Twy/cIgIykQu7JZA=="; };
It's important that the name of the key -- not just the binary data the key points to -- be identical on both ends of the transaction. If it's not, the recipient tries to verify the TSIG record and finds it doesn't know the key that the TSIG record says was used to compute the hash value. That causes errors like the following:
The algorithm, for now, is always hmac-md5. The secret is the base 64 encoding of the binary key. You can create a base 64-encoded key using the dnssec-keygen program included in BIND 9 or the dnskeygen program included in BIND 8. Here's how you'd create a key using dnssec-keygen, the easier of the two to use:Nov 21 19:43:00 wormhole named-xfer[30326]: SOA TSIG verification from server [192.249.249.1], zone movie.edu: message had BADKEY set (17)
The -a option takes as an argument the name of the algorithm the key will be used with. (That's necessary because dnssec-keygen can generate other kinds of keys, as we'll see in the DNSSEC section.) -b takes the length of the key as its argument; the RFC recommends using keys 128 bits long. -n takes as an argument HOST, the type of key to generate. (DNSSEC uses ZONE keys.) The final argument is the name of the key.# dnssec-keygen -a HMAC-MD5 -b 128 -n HOST terminator-wormhole.movie.edu. Kterminator-wormhole.movie.edu.+157+28446
dnssec-keygen and dnskeygen both create files in their working directories that contain the keys generated. dnssec-keygen prints the base name of the files to its standard output. In this case, dnssec-keygen created the files Kterminator-wormhole.movie.edu.+157+28446.key and Kterminator-wormhole.movie.edu.+157+28446.private. You can extract the key from either file. The funny numbers (157 and 28446), in case you're wondering, are the key's DNSSEC algorithm number (157 is HMAC-MD5) and the key's fingerprint (28446), a hash value computed over the key to identify it. The fingerprint isn't particularly useful in TSIG, but DNSSEC supports multiple keys per zone, so identifying which key you mean by its fingerprint is important.
Kterminator-wormhole.movie.edu.+157+28446.key contains:
and Kterminator-wormhole.movie.edu.+157+28446.private contains:terminator-wormhole.movie.edu. IN KEY 512 3 157 skrKc4Twy/cIgIykQu7JZA==
You can also choose your own key and encode it in base 64 using mmencode :Private-key-format: v1.2 Algorithm: 157 (HMAC_MD5) Key: skrKc4Twy/cIgIykQu7JZA==
Since the actual binary key is, as the substatement implies, a secret, we should take care in transferring it to our name servers (e.g., by using ssh) and make sure that not just anyone can read it. We can do that by making sure our named.conf file isn't world-readable or by using the include statement to read the key statement from another file, which isn't world-readable:% mmencode foobarbaz Zm9vYmFyYmF6
There's one last problem that we see cropping up frequently with TSIG: time synchronization. The timestamp in the TSIG record is useful for preventing replay attacks, but it tripped us up initially because the clocks on our name servers weren't synchronized. That produced error messages like the following:include "/etc/dns.keys.conf";
We quickly remedied the problem using NTP, the network time protocol. [82]Nov 21 19:56:36 wormhole named-xfer[30420]: SOA TSIG verification from server [192.249.249.1], zone movie.edu: BADTIME (-18)
[82]See the Time Synchronization Server web site at http://www.eecis.udel.edu/~ntp for information on NTP.
The key to configuring this is the server statement's keys substatement, which tells a name server to sign queries and zone transfer requests sent to a particular remote name server. This server substatement, for example, tells the local name server, wormhole.movie.edu, to sign all such requests sent to 192.249.249.1 (terminator.movie.edu) with the key terminator-wormhole.movie.edu:
Now, on terminator.movie.edu, we can restrict zone transfers to those signed with the terminator-wormhole.movie.edu key:server 192.249.249.1 { keys { terminator-wormhole.movie.edu.; }; };
terminator.movie.edu also signs the zone transfer, which allows wormhole.movie.edu to verify it.zone "movie.edu" { type master; file "db.movie.edu"; allow-transfer { key terminator-wormhole.movie.edu.; }; };
You can also restrict dynamic updates with TSIG by using the allow-update and update-policy substatements, as we showed you in the last chapter.
The nsupdate programs shipped with BIND 8.2 and later support sending TSIG-signed dynamic updates. If you have the key files created by dnssec-keygen lying around, you can specify either of those as an argument to nsupdate's -k option. Here's how you'd do that with BIND 9's version of nsupdate :
or:% nsupdate -k Kterminator-wormhole.movie.edu.+157+28446.key
With the BIND 8.2 or later nsupdate, the syntax is a little different: -k takes a directory and a key name as an argument, separated by a colon:% nsupdate -k Kterminator-wormhole.movie.edu.+157+28446.private
If you don't have the files around (maybe you're running nsupdate from another host), you can still specify the key name and the secret on the command line with the BIND 9 nsupdate :% nsupdate -k /var/named:terminator-wormhole.movie.edu.
The name of the key is the first argument to the -y option, followed by a colon and the base 64-encoded secret. You don't need to quote the secret since base 64 values can't contain shell metacharacters, but you can if you like.% nsupdate -y terminator-wormhole.movie.edu.:skrKc4Twy/cIgIykQu7JZA==
Michael Fuhr's Net::DNS Perl module also lets you send TSIG-signed dynamic updates and zone transfer requests. For more information on Net::DNS, see Chapter 15, "Programming with the Resolver and Name Server Library Routines".
Now that we've got a handy mechanism for securing DNS transactions, let's talk about securing our whole name server.