2015-04-11

On DNSSEC, Part 2 - I Actually Used DNSSEC Once

Let it never be said I didn't try.

I've pretty much given up on BIND as DNS server software, but that doesn't mean that DNSSEC is impossible to implement for your home usage. There are other packages out there, such as Unbound, which was made the default DNS resolver in OpenBSD 5.6 last year.

Assuming you want to use the default DNS resolver in a recent version of OpenBSD, it's simple enough to configure and run:

  1. Install OpenBSD 5.6 or later. I used a snapshot of 5.7.
  2. sudo unbound-anchor -v
  3. sudo cp -p /etc/rc.conf.local /etc/rc.conf.local.new
  4. Add unbound_flags="-c /var/unbound/etc/unbound.conf" to /etc/rc.conf.local.new.
  5. sudo mv /etc/rc.conf.local.new /etc/rc.conf.local
  6. Uncomment out the auto-trust-anchor-file line in /var/unbound/etc/unbound.conf. Save the file.
  7. Optional, but I recommend it, turn on logging. Add logfile: "/var/unbound/log/unbound.log" to unbound.conf and make sure /var/unbound/log exists and is writable by the _unbound user. There are additional logging options you can explore.
  8. Reboot.

Edit your /etc/resolv.conf file to use nameserver 127.0.0.1, which is increasingly non-trvial anymore. On recent OpenBSD deployments, you can add supersede domain-name-servers 127.0.0.1; to /etc/dhclient.conf to prevent DHCP leases from overwriting your changes.

If all goes according to plan, you can now do signed DNS queries where applicable. I use michaelwlucas.com as my go-to DNSSEC query domain because unlike isc.org, I trust that he's read the documentation:

$ dig +dnssec michaelwlucas.com a
; <<>> DiG 9.4.2-P2 <<>> +dnssec michaelwlucas.com a
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47389
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;michaelwlucas.com.             IN      A

;; ANSWER SECTION:
michaelwlucas.com.      7178    IN      A       104.236.197.233
michaelwlucas.com.      7178    IN      RRSIG   A 8 2 7200 20150419154845 20150320153915 23085 michaelwlucas.com. B0m6vsfOyRfjEtuLbvBHnCHxywZhhuwdoBei3RbaYXnlqdURZRXlC3bS /1D5VuFw0AK6xNvia1wUUIUfEXy68kdJ2lUjfZlTwkO1kRmu5gjx2dUj ohV9wefIbhzrAzStaW3tbhDaHwP88PAhGCnJSHbeAjND2qrEh6a3xWdJ Dbo=

The key here is to look for the AD flag so you don't have to think about it too much. Congrats! You're finished with DNSSEC! Forever!

OK, real talk. What's going on here? You need to start with an anchor file, which if you're super paranoid you can cross-reference with the signed root zone and Registry Administrator PGP key (1024D/0BD07395). No one in his right mind would ever do that, let alone have Perl scripts that do it regularly and point his resolvers there.

So what's the deal with the anchor file? If you don't have one with which to start, unbound-anchor uses a hard-coded anchor file and hard-coded certificate to fetch https://data.iana.org/root-anchors/root-anchors.xml over SSL and parse it. I am not making this up. There's a mechanism to keep tabs on what the latest and greatest keys are, but there's no good way to join that party if you aren't already a member. You have to start by scraping a web page and hoping your HTTPS hasn't been MITMed. Having looked through the code, I don't think they actually do any PGP validation. You only get that if you do it deliberately, by hand.

You also have to check to make sure your clock is right, because if it's wildly inaccurate, you're going to have a bad time. It fails if your clock reads before 2010-07-15 (root wasn't signed before then), if your clock is behind by a greater length of time than the RFC-5011 update window, or if the hard-coded cert ever expires or your clock says it has. That's 2029-12-18, so no rush there. And this is just running DNSSEC on our resolver. I haven't even touched what it would take to put DNSSEC on top of your existing authoritative DNS data.

So now, we're really basing our trust of our DNS anchor on HTTPS. And if we jump on the DANE bandwagon, we get to put HTTPS in the hands of DNS, which is actually setup with... HTTPS. At some point I guess we're going to get to divide by zero.

What do we gain by using DNSSEC? Signatures! Lots of 'em! Well, actually, some of 'em. DNSSEC has some piss-poor deployment stats, so you don't get secure DNS, you get signatures where and when admins choose to sign things. DNSSEC is designed to check for the validity of signatures either up or down the chain to or from the root. You can start from the bottom and work your way up, or vice-versa. None of this is encrypted of course, so an outside observer can see everything you're doing. The advantage of DNSSEC over default DNS is that an attacker has a harder time changing the responses you receive. Fun fact: an attacker has no problem caching signed responses and feeding them back to you after the real records have changed. A signature has a validity period, usually 30 days, and if you ask an unencrypted question, don't be surprised to get an unencrypted answer, even if that answer is out-of-date.

So is DNSSEC better than nothing? Yes and no, it depends on what you need. It doesn't really secure the DNS like we need it to be secured. With DNSSEC, it's all or nothing: if a domain isn't signed, you're back to using default DNS. If a domain is signed but the configuration is even slightly wrong anywhere in the chain, you don't get a "something seems wrong" result, you get a total blackout. From a security perspective, this is a good thing, but it has its consequences. If you ignore any result that doesn't match your expected signature, you stay safe from forgery, but you wind up with a very brittle key management mechanism that makes rollovers risky.

DNSSEC also uses a centralized authentication chain. Your domain keys need to get signed by the next key up, and so on, and so on, before everything works as planned. And if you make a mistake, you have to propagate the fix in the same manner: low TTLS are essential for debugging your setup but kill your caching layer. Even DNSSEC proponents insist that This Matters.

So assuming we are OK with how DNSSEC is structured (we're not) and we can avoid configuration errors that result in denial of service (we can't), what does DNSSEC do for us?

With DANE, it would tie certificate trust to this central chain of trust. Great! Now when DNSSEC breaks, certs go away! When a cert breaks, you need to make a new one, deploy it, and then DNSSEC needs to sign the update! HTTPS becomes a problem for the DNS administrators to maintain, and certs are still going to expire just like how Google misses renewal memos once in a while, too. DNSSEC wouldn't prevent this, it would just make it take a little longer to recover from an outage.

And even though secure SMTP sucks these days, DANE isn't going to fix it. It couldn't, unless you put the cert into the DNS record of the MTA somehow. The connection needs to be encrypted from byte 1, sort of like how HTTPS works. Hmmmm. Interesting idea.

As a wise man once tweeted, "Any unencrypted traffic, visible to an adversary, is not just an information leak, but an attack vector they can use to exploit your systems[.]" If we take this advice to heart, DNSSEC is a non-starter. Queries aren't encrypted, and even if you can trust that the information you've received is correct, it's harmful to you if other people can see the same information. Since DNSSEC doesn't, cannot, — and explicitly will not — encrypt your queries, it will remain an attack vector to anyone who can break a 1024-bit key. 280 operations isn't so astronomical anymore. Ignoring the fun little replay attacks you could do and corruption injections that are feasible in an un-encrypted, connectionless protocol, breaking a key or silently backdooring your RSA key generation algorithm altogether isn't totally impossible these days.

Next time: Nobody's business, including the Turks.

No comments: