The DNSSEC Diaries, Ch. 1: Names And Places
DNSSEC gives developers the ability to authenticate small bits of trusted data in a namespace that transcends organizational boundaries.
That’s great, because application developers have a real problem authenticating across organizational boundaries. PKI based on X.509 was supposed to fix this, but a couple billion dollars in failed deployments later, it’s become painfully clear: X.509 is really quite expensive and painful.
But developers don’t have a problem doing DNS lookups — complex as distributed databases are, DNS operations coalesce into a small bit of code that’s completely abstracted away. If developers could authenticate peers, as easily as they could look up an IP address — well, we’d see a lot more authentication.
And a lot fewer password prompts.
But — to be plainly honest — DNSSEC was not originally designed for user applications to validate just any small bits of trusted data. The original vision was somewhat constrained to validating IP addresses being sought after by a special subset of systems known as Name Servers.
That’s OK. Believe me, Tim Berners-Lee had no idea when he originally designed much of the web, that practically every page delivered would be dynamically generated from some managed language like Java, C#, or PHP, or would come from complex, worldwide load-balanced Content Distribution Networks. But there was nothing in the protocol that required pages be static files on a hard drive somewhere. And look what you could do, if you just dreamed a little bigger…
So, lets say we agree that DNSSEC should be used to push more than just IP addresses to name servers. There are a number of questions to be asked, regarding how this would work — questions I’ll address in further DNSSEC Diaries — but chief among them:
What exactly are we going to put into DNS?
Note, I said DNS, not DNSSEC. Really, DNSSEC is really just DNS with signatures, making it a more conservative design than people realize. You put whatever you want into your DNS. It’s just that DNSSEC validates that it’s you who put it there.
At this point, a lot of people have recognized that the first thing we want to migrate into DNS are public keys, or least hashes of them. (If you need help understanding what a public key is: Think of it as your face — easy for you to validate, hard for anyone else to clone. Putting a public key in DNS and securing it with DNSSEC is then just like getting a passport: Take a photo, put your name next to it, and then overlay an anti-counterfeiting hologram to link the two.)
Sounds pretty nice — but what does it look like on the wire? There’s actually quite a few options here. There are two major degrees of freedom when designing what’s known as the schema for trusted key information in DNS:
- Where will public key data for http://www.foo.com reside?
- What will public key data in http://www.foo.com look like?
There are no right answers here, only engineering tradeoffs. Quite a few teams are working on balancing the various engineering constraints involved, to make the best possible product — the KeyAssure group, for example. What I’d like to set out to do, is explain my thinking behind what’s presently implemented in Phreebird Suite 1.02. It’s my engineering philosophy that standards design works much better when people can understand why others built things a certain way, compare working code, and see what actually works well operationally in the field.
Lets tackle the first question: Where will trusted data reside? Given a domain, http://www.foo.com, there are in fact three places trusted information can be stored:
- Direct: http://www.foo.com
- Indirect: _keydata.www.foo.com
- Indirect with Marker Label: _keydata._ex.www.foo.com
It also turns out that there is something called an RRTYPE, or a Resource Record Type. When you query for a name, you can say that you’re interested in an IPv4 address, or an IPv6 address, or any of a number of other things. There are three competitors for what RRTYPE to query:
- CERT — an already specified, somewhat sub-typable record type
- TXT — a “blank” RRTYPE designed for textual data
- Custom — a new, unassigned RRTYPE, designed from scratch to contain certificate data
As you can see, even before we’ve gotten around to what the DNS answer looks like, specifying the DNS question is enough to start a holy war. That’s OK — holy wars are oddly common in DNS. Even simple things like returning different IP addresses depending on load or geographic location of the user are controversial! But we’ve got to start somewhere.
For Phreebird Suite 1.02, I’ve presently chosen: Direct naming (whenever possible, which won’t be always), with TXT encoding.
Lets start by discussing why Direct naming.
Direct naming maintains maximum compatibility with DNS redirection and wildcards. Most of the time, DNS is explained as a simple chain, i.e.:
- http://www.dankaminsky.com = [root] -> com’s name server -> dankaminsky.com’s name server -> 188.8.131.52
Often however, a CNAME is involved. A CNAME, or Canonical Name, lets DNS say “the answer to the name you resolved, is actually the answer to this entirely different name”. CNAME redirection is quite common, especially on larger sites. For example, for http://www.nbc.com:
- http://www.nbc.com = [root] -> com’s name server -> nbc.com’s name server -> CNAME to http://www.nbc.com.edgesuite.net.
- http://www.nbc.com.edgesuite.net. = [root] -> com’s name server -> Edgesuite’s name server -> CNAME to a1669.b.akamai.net.
- a1669.b.akamai.net. = [root] -> com’s name server -> Akamai’s name server -> 184.108.40.206
And thus, through twelve or so lookups, http://www.nbc.com resolves to 220.127.116.11.
(Performance isn’t as bad as the above implies, mainly because so many of the links are easily cached. Akamai basically invented CDNs, so they wouldn’t be doing this if it wasn’t speeding things up.)
Now, here’s where things get interesting. Suppose we want to express, in DNS, that the public key for http://www.nbc.com has a hash of 50ac1234. With Direct naming, all we have to do is put this information in a1669.b.akamai.net, and we’re done. A lookup against http://www.nbc.com will transition through the existing edgesuite and a16669 CNAMEs and resolve perfectly.
To put it another way — when CBS CNAMEs to Edgesuite or Akamai, it doesn’t need to think about what particular IP address Akamai will choose to route traffic to. It also doesn’t need to think about who else is being routed to that particular domain within Akamai. It just forwards the name, and Akamai figures out the IP.
Now, Akamai can figure out the public key as well. It’s really quite elegant, way easier than what we have to do with X.509 today.
By contrast, any other name will require new CNAMEs — _keyhash.www.nbc.com to _keyhash.www.nbc.com.edgesuite.net, and _keyhash.www.nbc.com.edgesuite.net to _keyhash.a1669.b.akamai.net., for example. Can you imagine how many meetings this would take? This is not operationally viable.
And this only covers the possible. Suppose for a moment that there exists *.nbc.com. With Direct naming, it’s trivial to have this wildcard CNAME to a single Akamai address, with its particular public key. But Indirect naming is difficult to impossible to support, since it requires a _keyhash.*.nbc.com wildcard — a style of wildcard not supported by any present name server, and extremely difficult to implement within the confines of most DNSSEC implementations.
So, as much as I like the named types we get from prefixes, they would cost us too much of DNS’s real world expressiveness. I do still have a use for them, though — I’ll describe it later.