In the section called “Easy Start Guide for Recursive Servers”, we used one line of configuration to turn on DNSSEC validation, the act of chasing down signatures and keys, making sure they are authentic. Now we are going to take a closer look at what it actually does, and some other options.
options { dnssec-validation auto; };
This “auto” line enables automatic DNSSEC
trust anchor configuration using the managed-keys
feature. In this case, no manual key configuration is needed.
There are three possible choices for the
dnssec-validation
option:
Let's discuss the difference between yes
and
auto
. If you set it to
yes
(the default), the trust anchor will need to
be manually defined and maintained using the trusted-keys
statement in the configuration file; if you set it to
auto
(as shown in the example), then no further
action should be required as BIND includes a copy[2] of the
root key. When set to auto
, BIND will
automatically keep the keys (also known as trust anchors, which we will look
at in the section called “Trust Anchors”) up-to-date without intervention from
the DNS administrator.
We recommend auto
unless you
have a good reason for requiring a manual trust anchor. To learn
more about trust anchors, please refer to the section called “Trusted Keys and Managed Keys”.
dnssec-enable
needs to be set to yes (default value is
yes) in order for dnssec-validation
to be effective.
So by now you've enabled validation on your recursive name server, and
verified that it works. What exactly changed? In the section called “How Does DNSSEC Change DNS Lookup?” we looked at the very high
level, simplified 12-steps of DNSSEC validation process. Let's revisit that
process now and see what your validating resolver is doing in more detail.
Again, we are using the example to lookup the A record for the domain name
www.isc.org
(Figure 1.1, “DNSSEC Validation 12 Steps”):
isc.org
name servers for
the A record of www.isc.org
. This query has the DNSSEC
OK
(do
) bit set to 1, notifying the remote
authoritative server that DNSSEC answers are desired.isc.org
is signed, and its name servers are
DNSSEC-aware, thus it responds with the answer to the A record query plus
the RRSIG for the A record.isc.org
.isc.org
name server responds with the DNSKEY and
RRSIG records. The DNSKEY is used to verify the answers received in
#2..org
) for the
DS record for isc.org
..org
name server responds with the DS and RRSIG
records. The DS record is used to verify the answers received in
#4..org
..org
name server responds with DNSKEY and RRSIG. The
DNSKEY is used to verify the answers received in #6..org
.After step #12, the validating resolver takes the DNSKEY received and compares to the key or keys it has configured, to decide whether or not the received key can be trusted. We will talk about these locally configured keys, or trust anchors, in the section called “Trust Anchors”.
As you can see here, with DNSSEC, every response includes not just the answer, but a digital signature (RRSIG) as well. This is so the validating resolver can verify the answer received, and that's what we will look at in the next section, the section called “How are Answers Verified?”.
So how exactly are DNSSEC answers verified? Before we can talk about how they are verified, let's first see how verifiable information is generated. On the authoritative server, each DNS record (or message) is run through a hash function, then this hashed value is encrypted by a private key. This encrypted hash value is the digital signature.
When the validating resolver queries for the resource record, it receives both the plain-text message and the digital signature(s). The validating resolver knows the hash function used (listed in the digital signature record itself), so it can take the plain-text message and run it through the same hash function to produce a hashed value, let's call it hash value X. The validating resolver can also obtain the public key (published as DNSKEY records), decrypt the digital signature, and get back the original hashed value produced by the authoritative server, let's call it hash value Y. If hash values X and Y are identical, and the time is correct (more on what this means below), the answer is verified, meaning we know this answer came from the authoritative server (authenticity), and the content remained intact during transit (integrity).
Take the A record www.isc.org
for example, the plain text
is:
www.isc.org. 4 IN A 149.20.64.69
The digital signature portion is:
www.isc.org. 4 IN RRSIG A 5 3 60 (
20141029233238 20140929233238
4521 isc.org.
DX5BaGVd4KzU2AIH911Kar/UmdmkARyPhJVLr0oyPZaq
5zoobGqFI4efvzL0mcpncuUg3BSU5Q48WdBu92xinMdb
E75zl+adgEBOsFgFQR/zqM3myt/8SngWm4+TQ3XFh9eN
jqExHZZuZ268Ntlxqgf9OmKRRv8X8YigaPShuyU= )
When a validating resolver queries for the A record
www.isc.org
, it receives both the A record and the RRSIG record.
It runs the A record through a hash function (in this example, it would be
SHA1 as indicated by the number 5, signifying RSA-SHA1) and produces hash
value X. The resolver also fetches the appropriate DNSKEY record to decrypt
the signature, and the result of the decryption is hash value Y.
But wait! There's more! Just because X equals Y doesn't mean everything is good. We still have to look at the time. Remember we mentioned a little earlier that we need to check if the time is correct? Well, look at the two highlighted timestamps in our example above, the two timestamps are:
This tells us that this signature was generated UTC September 29th, 2014, at 11:32:38PM (20140929233238), and it is good until UTC October 29th, 2014, 11:32:38PM (20141029233238). And the validating resolver's current system time needs to fall between these two timestamps. Otherwise the validation fails, because it could be an attacker replaying an old captured answer set from the past, or feeding us a crafted one with incorrect future timestamps.
If the answer passes both hash value check and timestamp check, it is
validated, and the authenticated data (ad
) bit is set, and
response is sent to the client; if it does not verify, a SERVFAIL is returned
to the client.
[2] BIND
technically includes two copies of the root key, one is in
bind.keys.h
and is built into the executable, and one is
in bind.keys
as a managed-keys
statement. The two copies of the key are identical.