Adopting DNSSEC
The Domain Name System (DNS) is an amazing technological achievement, but it suffers from a historical excess of trust, which makes it possible for people who rely on it to be lied to. The DNS Security Extensions (formally DNSSEC-bis, more usually just DNSSEC) are a mechanism for including robust trust information within the DNS. Here we discuss briefly what DNSSEC does, how it does it, and how (and whether) you can use it to secure your domains.
The problem
DNS is the distributed system that maps domain names to IP addresses; it is one the largest distributed databases in the world. However, its design dates back to an earlier era when there was more trust around; specifically, information propagated by the DNS is often cached, while only being validated by checking the IP address of the supplier.
There are at least two problems with this. First, just because a DNS packet comes from the configured resolver is not necessarily a good reason to assume the content is trustworthy. And second, because much DNS information is propagated via UDP, which makes spoofing sender IP addresses trivial, a DNS packet claiming to be from the configured resolver's IP address may not actually come from that resolver.
The fascinating field of security research has unearthed many ingenious attacks against cryptographic protocols, such as power analysis, which are elegant and effective but unlikely to be seen in quantity in the wild anytime soon. DNS spoofing, though, is widespread; it's easy to do, and lots of people are doing it, for all sorts of reasons.
In March 2014, Turkey blocked access to Twitter after recordings damaging to the Turkish government were leaked there. The country did this by instructing Turkish ISPs to return wrong IP address information when twitter.com domains were resolved, so that DNS would instead return IP addresses that took users to a government web page announcing the block. Turks quickly discovered that setting their DNS servers to foreign recursing resolvers such as Google's would bypass the block, and some went a step further by spray-painting the IP addresses of Google's DNS servers on public buildings. Other governments engage in similar practices on a routine basis.
The solution
It's been slow in coming, but DNSSEC is now pretty much here. It enables cryptographic signatures to be distributed in the DNS alongside existing information, so that resolvers that care about such things can ask for it; they can also rely upon the answers they get. This is done by defining a few new DNS Resource Record (RR) types:
- RRSIG: This one's the workhorse; it's a signature for an RR, made with the appropriate key pair. To verify the authenticity of some RR that has just been queried, whether it was an A record, an MX, a CNAME, or some other record, the accompanying RRSIG is the starting point.
- DNSKEY: This asserts one of the keys (yes, plural, we'll come to that) for a particular zone or subzone. This is something given out to the world for your own zone(s), much like an SSH server announcing its own public key on connection.
- DS: This is how trust is distributed. It's a fingerprint for the primary DNSKEY record, generated by the zone's parent (usually, the registrar) and distributed as part of the glue. Like any other RR, it also comes with an RRSIG record, also generated by the zone's parent. This is how people can trust your DNSKEY records when you return them in response to a query. Its existence also functions as a flag that DNSSEC extensions should be checked by a capable resolver for queries in the zone in question.
- NSEC3: It is as important to sign your negative responses as your positive ones, otherwise any attacker could simply sit there returning faked NXDOMAIN responses for queries about all your hostnames. NSEC3 provably says that no such RR exists, in such a way as to cover a range of possible name queries without enabling a brute-force search of the namespace.
Can I use it? Should I? How do I?
Not all top-level domains (TLDs) currently implement DNSSEC. Wikipedia's list of TLDs includes information on which do and do not support DNSSEC, but it's pretty widely supported, and if you're not doing registration in some obscure country-code TLD just to get a cute domain name, you probably can deploy DNSSEC.The following shows how I enabled DNSSEC on teaparty.me.uk by following a procedure which was developed from NLNetLabs' excellent HOWTO, to whose authors I am grateful. You will need to be using a BIND implementation that is DNSSEC-capable, but I'm using BIND 9.8.2 on CentOS 6, which is pretty old, and it works fine.
First, you have to generate your zone keys. Second, you have to include your keys in your zone file and sign your zone. Finally, you have to generate your DS record, and propagate it through your registrar.
So, first off, generate the keys. They come in two types: a key-signing key (KSK), which is used only to sign other keys, and a zone-signing key (ZSK), which is used to sign all the other RRs. These do not have to be different keys, but best practice is to use a different KSK and ZSK. Key lengths and algorithm choices are a matter for you to decide. Also, the choice between /dev/random and /dev/urandom is yours to make; my server has a hardware random-number generator (RNG) attached, without which this process might have taken some time. Note also that I do this in the parent of the directory that holds the zone files themselves, as I find it convenient to keep the keys there.
[root@lory dns]# dnssec-keygen -r/dev/random -f KSK -a RSASHA1 -b 2048 teaparty.me.uk
Generating key pair...............................+++ ..........................+++
Kteaparty.me.uk.+005+02104
[root@lory dns]# dnssec-keygen -r/dev/random -a RSASHA1 -b 2048 teaparty.me.uk
Generating key pair.....+++ .................+++
Kteaparty.me.uk.+005+60996
Here, the -b chooses the key length and the -a is used to
choose the cryptographic algorithm to be used.
The last line of the output in each case is the base name of the
key files, one ending .key and the other ending in
.private, which have just been created in the working
directory. The filename includes the zone name, the algorithm type (005=RSA/SHA-1),
and a five-digit random key identifier
which helps detect key rollovers (about which more
may be found here). Now, let's extract the meat, that being the
new keys, from those .key files we just created:
[root@lory dns]# grep DNSKEY *teaparty.me.uk*.key
Kteaparty.me.uk.+005+02104.key:teaparty.me.uk. IN DNSKEY 257 3 5 AwEAAdCM/LeSga8...
Kteaparty.me.uk.+005+60996.key:teaparty.me.uk. IN DNSKEY 256 3 5 AwEAAcQxmpGFwWw...
The keys in the above output have been truncated to avoid filling
your screen with gibberish. Note the leading 256 and 257 in the
DNSKEY RRs: an even number indicates a ZSK and an odd number,
a KSK. Your KSK is your zone's primary key, from which we will later
derive your DS record.
Next up is to put the two DNSKEY RRs into your zone file, then sign it with the keys you have just created. Signing is accomplished with the dnssec-signzone command:
[root@lory ~]# cd /var/named/chroot/var/dns/primary/
[root@lory primary]# /usr/sbin/dnssec-signzone -o teaparty.me.uk \
-f teaparty.me.uk.signed -K .. -k Kteaparty.me.uk.+005+02104.key \
-e +3024000 -N unixtime teaparty.me.uk Kteaparty.me.uk.+005+60996.key
dnssec-signzone: warning: teaparty.me.uk:8: no TTL specified; using SOA MINTTL instead
Verifying the zone using the following algorithms: RSASHA1.
Zone signing complete:
Algorithm: RSASHA1: KSKs: 1 active, 0 stand-by, 0 revoked
ZSKs: 1 active, 0 stand-by, 0 revoked
teaparty.me.uk.signed
First, I changed into the directory where the zone file is (in whose
parent, you will recall, the keys are kept). Then I signed the zone;
important flags include:
- -o specifies the zone origin (domain name); this can be inferred from the filename, but I prefer to keep it explicit.
- -f specifies the file that will contain the signed zone; I will need to alter my named.conf file so that the zone is taken from this signed file in future.
- -K specifies where to find key files.
- -k specifies the file containing the KSK.
- -e specifies the date until which I wish the signatures to remain valid. +3024000s is now + 35 days, which is designed to let me automate this signing with cron on the first of every month without the signatures ever expiring, even if the leap second people at the IERS decide to put quite a lot of extra seconds onto the end of any given month.
- -N specifies that the zone serial number (SN) in the new, signed zone file will be Unix time. I could use -N keep to preserve the SN from the input unsigned, zone file, but I prefer this.
The last step is to generate your DS record from your KSK. This has already been done by signing the zone; you will notice in the zone file directory a file called, in my case, dsset-teaparty.me.uk.. This contains a couple of potential DS records that differ only in the digest type being used ("1" versus "2") and thus also in the digest of the key itself:
[root@lory primary]# cat dsset-teaparty.me.uk.
teaparty.me.uk. IN DS 2104 5 1 1E8AB98D...
teaparty.me.uk. IN DS 2104 5 2 440A7FA1... 6F8640BE
This can also be done manually with the dnssec-dsfromkey
command, which can be fed either the zone file or the KSK file.
Although RFC 4034
says that having a DS record with digest type 1 (SHA-1) is
mandatory, RFC
4509 defines the digest type 2 (SHA256) digest, and specifies that
digest type 1 should be ignored if type 2 is present, in keeping with
the move away from SHA-1. Most people seem to publish only the SHA-256
(digest type 2) record, and this works well for me.
So I will give the digest type 2 record to my registrar through whatever mechanism it has decided is appropriate. For registrations in .uk I do it through Nominet's website, being a registrar myself; alternatively, one would go through one's registrar. For .com/.net/.org domains, which I register through an old friend, I email the DS record to him under cover of PGP, and he passes it up the chain of registrars until it gets to someone who can put it into the proper TLD zone file.
And is it working?
You can check for DNSSEC capability in your normal resolution chain by using dig +trace. Try:
$ dig +trace www.google.com
If you
see a bunch of RRSIG and DS records being returned in
the chain along with the more usual A and NS records,
you're DNSSEC-capable. If your normal resolution chain isn't capable,
try:
$ dig +trace www.google.com @8.8.8.8
That will show whether your
client is
capable and so configured. You'll need a DNSSEC-capable resolver to go
any further.
If I take a DNSSEC-capable resolver, such as Fedora 24's, using a capable resolution chain such as Google's public servers, and I ask for explicit signature checks, I should get confirmation that all is well:
$ dig +sigchase test.teaparty.me.uk @8.8.8.8
...
;; Ok this DNSKEY is a Trusted Key, DNSSEC validation is ok: SUCCESS
If I alter the RRSIG on my A record by one byte,
increment the zone's SN, reload the zone, and repeat the test, I should
get indication of a problem, ending with:
;; Impossible to verify the Non-existence, the NSEC RRset can't be validated: FAILED
The usual sources of error are cut-and-paste failings, publishing a DS record without a signed zone (recall that the presence of the record is the indicator that a zone should be signed), or major clock skew in your DNS server. The latter can cause problems because TTLs in DNSSEC RRs are absolute timestamps, unlike the relative TTLs of pre-DNSSEC RRs; if clocks are badly wrong, RRs that are already out-of-date can be propagated, and these will fail to validate.
So in summary, DNSSEC isn't complex; honestly, it's not. It's fiddly,
to be sure; many small parts have to be assembled in the right order.
But once this is done, it just works, to the net benefit of all. If you
are in charge of any DNS infrastructure, and you haven't come to grips
with this already, now might be a good time for you to tackle DNSSEC.
| Index entries for this article | |
|---|---|
| Security | DNSSEC |
| GuestArticles | Yates, Tom |