How does DNSSEC work?

First, a quick background on DNS

DNS is often called the phone book of the internet. It's the protocol that translates domain names such as to IP addresses. However, although the whole Internet is heavily relying on it, it has one major security flaw: there is no guarantee for the end user in DNS that the records received have not been tampered. That means that DNS records can be forged to redirect browsers to fetch content from a malicious website, to add JavaScript to run on a page, or to route email to an attacker’s mail server, for example.

DNSSEC, an introduction

If we keep calling DNS the phone book of the Internet, we could say that DNSSEC is the protocol that ensures a number in the phone book actually belongs to the contact listed. It uses public-key cryptography to this end, and (in short):

  • lets the DNS server signs records with a private key
  • allows the DNS resolvers to verify the signatures with a public key

These public keys are vouched for by the parent zone (See below: Chain of Trust in DNSSEC).

DNSSEC in practice

Let's see what that looks like. The command-line tool dig lets you query a DNS server and print out the response. Using it to ask your DNS resolver what is (are) the IP address of “” goes like this.

$ dig +short

This tool shows by default the A records, and because of the option “+short”, it outputs the result only. If we want to see whether the records can be verified with DNSSEC, we can run:

$ dig +short +dnssec
A 13 3 300 20160316130645 20160314110645 35273 wIprzypq8AaxIP8c6n1/4rJYTzY752Pc0gbl6SlfddAE3rhfuJXondwQ 8/ZlPh3xxao9/riP18YgZAypzV5ZJw==

The last line you see is called the RRSIG record. It’s the DNSSEC signature attached to the record. This is the information the resolver would use to figure out whether you can trust the DNS response. Eventually, we can also retrieve the public key that needs to be used to verify this record:

$ dig DNSKEY +short
257 3 13 mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+ KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==
256 3 13 koPbw9wmYZ7ggcjnQ6ayHyhHaDNMYELKTqT+qRGrZpWSccr/lBcrm10Z 1PuQHB3Azhii+sb0PYFkH1ruxLhe5g==

Note, when searching for the public key, we ran a request with the whole domain as an argument, and not, because all the records of a domain are signed with the same key. Please note also, this actually shows two records:

  • the DNSKEY record with the flag '256' is the public key called Zone-signing-key, used to verify the signatures of the A, MX, CNAME, SRV, … records.
  • the DNSKEY record with the flag '257' is called the Key-Signing Key.

Theoretically, only one public key would be needed, but for reasons we’ll see below, there is two. The details on how to verify the signatures with the public key are beyond this article, but you can search what the option “+sigtrace” does in dig(1) manpage, or see what the unbound-host command does.

Chain of Trust in DNSSEC

So far in this article, all the responses to our queries were returned by the same nameserver, so whatever signature verification we do with this information is not enough: if the server has been compromised, most likely not only the records have been tampered with, but so have the keys and the signatures. We need to verify all this information against an external source.

To this end, the full verification of the signatures for a domain (for ex: “”) involves verifying the key-signing-key at the top-level-domain (here: “.com”), and then performing the same operation at the level above (checking the key-signing-key of “.com” at the root level).

That's why when you enable DNSSEC, you have to add a specific record (the DS record) at your registrar. The DS record stands for Delegation Signer, and it contains a hash of your public key as well as metadata about the key, such as what algorithm is uses.

You can view the DS record of “” by running:

$ dig +short DS
2371 13 2 32996839A6D808AFE3EB4A795A0E6A7A39A76FC52FF228B22B76F6D6 3826F2B9

You can also check that this answer has not been returned by the nameserver for “” but by the nameserver for “.com”, using the option “+trace”. I’m only showing the relevant bits here:

$ dig +trace DS
[...]         86400   IN      DS      2371 13 2 32996839A6D808AFE3EB4A795A0E6A7A39A76FC52FF228B22B76F6D6 3826F2B9
com.                    172800  IN      NS
;; Received 504 bytes from in 37 ms

So we now have the means to verify the signatures for “” against another signature that we received from another source. But running all the steps of this process manually would be laborious. A great way to visualise that the DNSSEC chain of trust is working (or not) for your domain (and if not, to check where it fails) is the following tool:

For example, for “”, here’s the output:

Hopefully, this explains to you how DNSSEC works. If you have specific questions on how to make it work at CloudFlare, please contact

Not finding what you need?

95% of questions can be answered using the search tool. This is the quickest way to get a response.

Powered by Zendesk