Cover V13, i10

Article

oct2004.tar

DNS Security Protocols II: DNSSEC

Kerry Thompson

This is the second of two articles examining the latest mechanisms for securing DNS. In the September 2004 issue of Sys Admin, I looked at securing dynamic updates and zone transfers with TSIG keys; in this article, I will look at the DNSSEC protocol for securing the zone data itself.

In conventional DNS usage, there is no guarantee that the data received by a name server or client is authoritative or that a name server is not maliciously providing false information. The DNSSEC system prevents clients from trusting information that is false. Under DNSSEC, all data must be authenticated and verified before it can be trusted. To prove that the data is authoritative and has not been tampered with, an authoritative source must create and digitally sign the data.

In the following examples, I'm using ISC BIND version 9.3.0rc2 from www.isc.org -- you will need to use version 9.3.0 of ISC BIND in order to usefully explore DNSSEC because previous versions used deprecated DNSSEC record types. If you are compiling this from the source, you will need to use the "--with-openssl" option to the ./configure command to enable the cryptographic functions, and you will also probably want to enable signature chasing support for the dig command. The commands to build BIND with these options are:

STD_CDEFINES="-DDIG_SIGCHASE=1"
export STD_CDEFINES
./configure --with-openssl
make
make install
As with the previous article, my test systems have been set up to serve a test domain "domain.tld" and a reverse domain "1.168.192.in-addr.arpa".

Secure DNS Zones

Making secure updates is good, but how can we ensure that the results of DNS queries actually came from an authoritative server and have not been modified in transit? The aim of the DNSSEC protocol extensions is to make sure DNS data comes from the correct server and cannot be changed.

To enable DNSSEC for a zone, we first generate two keys for the zone. These will become the key signing key (KSK) and the zone signing key (ZSK). For our test domain, use the following commands to generate the keys:

cd /var/named
dnssec-keygen -r /dev/urandom -a RSASHA1 -b 1024 -n ZONE domain.tld
dnssec-keygen -r /dev/urandom -a RSASHA1 -b 2048 -n ZONE domain.tld
dnssec-keygen -r /dev/urandom -a RSASHA1 -b 1024 -n ZONE 1.168.192.in-addr.arpa
dnssec-keygen -r /dev/urandom -a RSASHA1 -b 2048 -n ZONE 1.168.192.in-addr.arpa
Dnssec-keygen will generate the keys and put them into newly created key files with cryptic names such as Kdomain.tld.+005+14957.key. Here, we create a 1024-bit key, which will be used as the ZSK, and a 2048-bit key for the KSK. The numbers in the key file names designate the algorithm used to create the key (005 for RSASHA1) and a random 5-digit number to represent a key ID.

Next, insert these keys into the zone files and generate new signed zone files. Edit the domain.tld and 1.168.192.in-addr.arpa zone files and in each add the key file with $include statements. In the domain.tld file, add the following lines just after the SOA record:

# 1024-bit ZSK:
$include Kdomain.tld.+005+14957.key
# 2048-bit KSK:
$include Kdomain.tld.+005+61205.key
In the 1.168.192.in-addr.arpa file, add:

# 1024-bit ZSK:
$include K1.168.192.in-addr.arpa.+005+38921.key
# 2048-bit KSK:
$include K1.168.192.in-addr.arpa.+005+07571.key
Run the dnssec-signzone utility to sign the zone with the keys. This will take the zone file domain.tld and create a new, signed zone in domain.tld.signed:

dnssec-signzone -r /dev/urandom -t -k Kdomain.tld.+005+61205.key \
  domain.tld Kdomain.tld.+005+14957.key
dnssec-signzone -r /dev/urandom -t -k K1.168.192.in-addr.arpa.+005+07571.key \
  1.168.192.in-addr.arpa K1.168.192.in-addr.arpa.+005+38921
We use the -k option to specify the 2048-bit KSK to dnssec-signzone. Note that the names of the zone files are the same as the names of the DNS zones. If they're different, you need to specify extra options to dnssec-signzone.

If you look at the newly generated .signed files, you'll see that they have been filled with lots of extra records, with types such as NSEC, RRSIG, and DNSKEY. The DNSKEY record contains a copy of the public key for the zone, RRSIG contains a digital signature for a resource record (an RR), and NSEC records are used to provide an authenticated denial of existence for queries to unknown records.

Now edit /etc/named.conf and change the name of the data file for the zones to refer to the signed zone file. In my example for domain.tld and 1.168.192.in-addr.arpa, the named.conf entries become:

zone "domain.tld" IN {
      type master;
      file "domain.tld.signed";
      allow-update { key update_key; };
      allow-transfer { key slave_xfers_key; };
};

zone "1.168.192.in-addr.arpa" IN {
      type master;
      file "1.168.192.in-addr.arpa.signed";
      allow-update { key update_key; };
      allow-transfer { key slave_xfers_key; };
};
Also, add the option "dnssec-enable" into the options statement at the top of the named.conf file to enable the DNSSEC extensions:

options {
      directory "/var/named";
      dnssec-enable yes;
};
Restart named and check syslog for any errors. You should see messages stating that the signed zone has been loaded, similar to these:

named[910]: zone domain.tld/IN: loaded serial 4 (signed)
At this point, you can also send dynamic updates to add and delete records in the signed zones. This method is much easier than editing the original zone file and re-signing the records.

Testing DNSSEC Secure Zones

You can use the dig utility, which comes with BIND to check that your DNSSEC domain is functioning properly. By including the +dnssec option, you should receive the additional RRSIG and DNSKEY records for your query:

dig +dnssec @192.168.1.2 www.domain.tld
The client cannot verify the validity of the returned records unless it has a copy of the domain key. You can use the "+sigchase" dig option to perform this verification (refer to the dig man page for details).

Using Secure Zones for Non-DNSSEC Clients

There are currently no client-side resolver libraries that perform verification of DNSSEC records. So, how do client systems make use of the secure zones? The way to do this is to configure a forwarding DNS server that the client will use for lookups and that will perform the verification of signed records. Such a server should be "close" to the client, preferably on the same subnet.

To configure a forwarding server to utilize DNSSEC, simply add the public keys of the top-level zone of your DNSSEC tree into a "trusted-keys" section of named.conf and enable DNSSEC extensions in the options statement. For our test server, the entire named.conf for a verifying forwarder configuration is:

options {
  directory "/var/named";
  pid-file "/var/named/named.pid";
  forward only;
  forwarders {
    192.168.1.3;
  };

  dnssec-enable yes;
  dnssec-must-be-secure "domain.tld" yes;
  dnssec-must-be-secure "1.168.192.in-addr.arpa" yes;
};

zone  "." {
  type hint;
  file  "named.ca";
};

trusted-keys {
  # public KSK:
  "domain.tld." 256 3 5 "AQPhlHNZPFlrY/evopm....";
  "1.168.192.in-addr.arpa." 256 3 5 AQOsRH9Bt9dbA....";
};
I've truncated the data of the key data lines in this case. These can be quite long in practice. The syntax for the trusted-keys statement is:

trusted-keys {
  <domain> <flags> <protocol> <algorithm> <key-string>;
};
where the key fields can be extracted from the public key file generated for the respective zone.

The "dnssec-enable" option is necessary to enable the DNSSEC functionality in the server. The "dnssec-must-be-secure" option says that the records for the "domain.tld" zone MUST be verified to be secure by the forwarding server. If the verification fails, the client will get a SERVFAIL error and no record data. If dnssec-must-be-secure is set to "no" then the client will get the query results even if the verification fails.

Restart your forwarding server after changing /etc/named.conf and check syslog for any error messages.

You should now be able to perform lookups against your forwarding server and get the server to verify the signatures that it receives from the authoritative master server. If the forwarder fails to validate responses from a zone for which trusted keys have been configured, the client should receive a "SERVFAIL" error and not be given invalid data that fails verification. You can test this by shutting down your master server, editing the ".signed" zone file, and changing a record manually (such as the IP address of an A record). After starting the master server again (and restarting the forwarder to clear its cache) queries for the modified record should receive an error response rather than valid record data.

Note that debugging DNSSEC operations can be difficult due to the cryptic logging messages. The papers in the Resources section below should provide help.

Conclusion

In this article, I've shown briefly how to configure DNSSEC-signed zones to ensure the security of DNS zone data. The full implementation of DNSSEC is really much more involved. To properly secure a zone, the parent zone should have copies of the child zone's public key, which is then signed by the parent's key, and so on, up to the root zones that should have well-known public keys. This chain of trust is quite similar in structure to the chain of certificates used to secure Web servers using the https protocol.

DNSSEC is still quite experimental and changes are still being finalized by the IETF. The BIND beta code is a little buggy, but from this you should be able to see how it can be utilized. Some users have commented that there may be risks in deploying DNSSEC in production systems as it is not as fault-tolerant as classical DNS. For example, if the zone keys expire then the entire zone may become inaccessible.

There have even been proposals for using DNSSEC protocols as a method of securely distributing keys to form a Public Key Infrastructure (PKI) system. Using DNSSEC to securely distribute public keys, such as PGP or ssh keys, is left as an exercise for the reader.

Another thing to note when using DNSSEC is that the network packets are significantly larger than normal plain DNS. If the 512-byte packet size is exceeded, systems will start using the TCP transport rather than UDP. Also, be careful of key expiry and be prepared to roll over keys. The papers in the References section explain how to do this.

References

DNSSEC project Web site with many useful resources -- http://www.dnssec.net

BIND v9 ARM (Administrators Reference Manual) -- http://www.nominum.com/content/documents/bind9arm.pdf

DNSSEC Operations HOWTO -- http://www.ripe.net/disi/Course/TechCourse.pdf

Nominum DNSSEC FAQ -- http://www.nominum.com/getOpenSourceResource.php?id=8

Kerry Thompson is a CISSP-certified security consultant for Open Systems Specialists in Auckland, New Zealand. He has been working in Unix systems administration and security for many years and regularly writes papers on IT security. Contact him at kerry@crypt.gen.nz.