857 lines
35 KiB
ReStructuredText
857 lines
35 KiB
ReStructuredText
.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
..
|
|
.. SPDX-License-Identifier: MPL-2.0
|
|
..
|
|
.. This Source Code Form is subject to the terms of the Mozilla Public
|
|
.. License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
..
|
|
.. See the COPYRIGHT file distributed with this work for additional
|
|
.. information regarding copyright ownership.
|
|
|
|
.. _DNSSEC_validation:
|
|
|
|
Validation
|
|
----------
|
|
|
|
.. _easy_start_guide_for_recursive_servers:
|
|
|
|
Easy-Start Guide for Recursive Servers
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
This section provides the basic information needed to set up a
|
|
working DNSSEC-aware recursive server, also known as a validating
|
|
resolver. A validating resolver performs validation for each remote
|
|
response received, following the chain of trust to verify that the answers it
|
|
receives are legitimate, through the use of public key cryptography and
|
|
hashing functions.
|
|
|
|
.. _enabling_validation:
|
|
|
|
Enabling DNSSEC Validation
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
So how do we turn on DNSSEC validation? It turns out that you may not need
|
|
to reconfigure your name server at all, since the most recent versions of BIND 9 -
|
|
including packages and distributions - have shipped with DNSSEC validation
|
|
enabled by default. Before making any configuration changes, check
|
|
whether you already have DNSSEC validation enabled by following the steps
|
|
described in :ref:`how_to_test_recursive_server`.
|
|
|
|
In earlier versions of BIND, including 9.11-ESV, DNSSEC
|
|
validation must be explicitly enabled. To do this, you only need to
|
|
add one line to the :namedconf:ref:`options` section of your configuration file:
|
|
|
|
::
|
|
|
|
options {
|
|
...
|
|
dnssec-validation auto;
|
|
...
|
|
};
|
|
|
|
Restart :iscman:`named` or run :option:`rndc reconfig`, and your recursive server is
|
|
now happily validating each DNS response. If this does not work for you,
|
|
you may have some other network-related configurations that need to be
|
|
adjusted. Take a look at :ref:`network_requirements` to make sure your network
|
|
is ready for DNSSEC.
|
|
|
|
.. _effect_of_enabling_validation:
|
|
|
|
Effects of Enabling DNSSEC Validation
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Once DNSSEC validation is enabled, any DNS response that does not pass
|
|
the validation checks results in a failure to resolve the domain name
|
|
(often a SERVFAIL status seen by the client). If everything has
|
|
been configured properly, this is the correct result; it means that an end user has
|
|
been protected against a malicious attack.
|
|
|
|
However, if there is a DNSSEC configuration issue (sometimes outside of
|
|
the administrator's control), a specific name or sometimes entire
|
|
domains may "disappear" from the DNS, and become unreachable
|
|
through that resolver. For the end user, the issue may manifest itself
|
|
as name resolution being slow or failing altogether; some parts of a URL
|
|
not loading; or the web browser returning an error message indicating
|
|
that the page cannot be displayed. For example, if root name
|
|
servers were misconfigured with the wrong information about ``.org``, it
|
|
could cause all validation for ``.org`` domains to fail. To end
|
|
users, it would appear that all ``.org`` web sites were out of service.
|
|
[#wrong_root_addr]_ Should you encounter DNSSEC-related problems, don't
|
|
be tempted to disable validation; there is almost certainly a solution
|
|
that leaves validation enabled. A basic troubleshooting guide can be
|
|
found in :ref:`dnssec_troubleshooting`.
|
|
|
|
.. [#wrong_root_addr]
|
|
Of course, something like this could happen for reasons other than
|
|
DNSSEC: for example, the root publishing the wrong addresses for the
|
|
``.org`` nameservers.
|
|
|
|
.. _how_to_test_recursive_server:
|
|
|
|
So You Think You Are Validating (How To Test A Recursive Server)
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Now that you have reconfigured your recursive server and
|
|
restarted it, how do you know that your recursive name server is
|
|
actually verifying each DNS query? There are several ways to check, and
|
|
we've listed a few of them below.
|
|
|
|
.. _using_web_based_tests_to_verify:
|
|
|
|
Using Web-Based Tools to Verify
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
For most people, the simplest way to check if a recursive name server
|
|
is indeed validating DNS queries is to use one of the many web-based
|
|
tools available.
|
|
|
|
Configure your client computer to use the newly reconfigured recursive
|
|
server for DNS resolution; then use one of these web-based tests to
|
|
confirm that it is in fact validating DNS responses.
|
|
|
|
- `Internet.nl <http://conn.internet.nl/connection/>`__
|
|
|
|
- `DNSSEC or Not (VeriSign) <https://www.dnssec-or-not.com/>`__
|
|
|
|
.. _using_dig_to_verify:
|
|
|
|
Using :iscman:`dig` to Verify
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Web-based DNSSEC-verification tools often employ JavaScript. If you don't trust the
|
|
JavaScript magic that the web-based tools rely on, you can take matters
|
|
into your own hands and use a command-line DNS tool to check your
|
|
validating resolver yourself.
|
|
|
|
While :iscman:`nslookup` is popular, partly because it comes pre-installed on
|
|
most systems, it is not DNSSEC-aware. :iscman:`dig`, on the other hand, fully
|
|
supports the DNSSEC standard and comes as a part of BIND. If you do not
|
|
have :iscman:`dig` already installed on your system, install it by downloading
|
|
it from ISC's `website <https://www.isc.org/download>`__.
|
|
|
|
:iscman:`dig` is a flexible tool for interrogating DNS name servers. It
|
|
performs DNS lookups and displays the answers that are returned from the
|
|
name servers that were queried. Most seasoned DNS administrators use
|
|
:iscman:`dig` to troubleshoot DNS problems because of its flexibility, ease of
|
|
use, and clarity of output.
|
|
|
|
The example below shows how to use :iscman:`dig` to query the name server 10.53.0.1
|
|
for the A record for ``ftp.isc.org`` when DNSSEC validation is enabled
|
|
(i.e. the default). The address 10.53.0.1 is only used as an example;
|
|
replace it with the actual address or host name of your
|
|
recursive name server.
|
|
|
|
::
|
|
|
|
$ dig @10.53.0.1 ftp.isc.org. A +dnssec +multiline
|
|
|
|
; <<>> DiG 9.16.0 <<>> @10.53.0.1 ftp.isc.org a +dnssec +multiline
|
|
; (1 server found)
|
|
;; global options: +cmd
|
|
;; Got answer:
|
|
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48742
|
|
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
|
|
|
|
;; OPT PSEUDOSECTION:
|
|
; EDNS: version: 0, flags: do; udp: 4096
|
|
; COOKIE: 29a9705c2160b08c010000005e67a4a102b9ae079c1b24c8 (good)
|
|
;; QUESTION SECTION:
|
|
;ftp.isc.org. IN A
|
|
|
|
;; ANSWER SECTION:
|
|
ftp.isc.org. 300 IN A 149.20.1.49
|
|
ftp.isc.org. 300 IN RRSIG A 13 3 300 (
|
|
20200401191851 20200302184340 27566 isc.org.
|
|
e9Vkb6/6aHMQk/t23Im71ioiDUhB06sncsduoW9+Asl4
|
|
L3TZtpLvZ5+zudTJC2coI4D/D9AXte1cD6FV6iS6PQ== )
|
|
|
|
;; Query time: 452 msec
|
|
;; SERVER: 10.53.0.1#53(10.53.0.1)
|
|
;; WHEN: Tue Mar 10 14:30:57 GMT 2020
|
|
;; MSG SIZE rcvd: 187
|
|
|
|
The important detail in this output is the presence of the ``ad`` flag
|
|
in the header. This signifies that BIND has retrieved all related DNSSEC
|
|
information related to the target of the query (``ftp.isc.org``) and that
|
|
the answer received has passed the validation process described in
|
|
:ref:`how_are_answers_verified`. We can have confidence in the
|
|
authenticity and integrity of the answer, that ``ftp.isc.org`` really
|
|
points to the IP address 149.20.1.49, and that it was not a spoofed answer
|
|
from a clever attacker.
|
|
|
|
Unlike earlier versions of BIND, the current versions of BIND always
|
|
request DNSSEC records (by setting the ``do`` bit in the query they make
|
|
to upstream servers), regardless of DNSSEC settings. However, with
|
|
validation disabled, the returned signature is not checked. This can be
|
|
seen by explicitly disabling DNSSEC validation. To do this, add the line
|
|
``dnssec-validation no;`` to the "options" section of the configuration
|
|
file, i.e.:
|
|
|
|
::
|
|
|
|
options {
|
|
...
|
|
dnssec-validation no;
|
|
...
|
|
};
|
|
|
|
If the server is restarted (to ensure a clean cache) and the same
|
|
:iscman:`dig` command executed, the result is very similar:
|
|
|
|
::
|
|
|
|
$ dig @10.53.0.1 ftp.isc.org. A +dnssec +multiline
|
|
|
|
; <<>> DiG 9.16.0 <<>> @10.53.0.1 ftp.isc.org a +dnssec +multiline
|
|
; (1 server found)
|
|
;; global options: +cmd
|
|
;; Got answer:
|
|
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39050
|
|
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
|
|
|
|
;; OPT PSEUDOSECTION:
|
|
; EDNS: version: 0, flags: do; udp: 4096
|
|
; COOKIE: a8dc9d1b9ec45e75010000005e67a8a69399741fdbe126f2 (good)
|
|
;; QUESTION SECTION:
|
|
;ftp.isc.org. IN A
|
|
|
|
;; ANSWER SECTION:
|
|
ftp.isc.org. 300 IN A 149.20.1.49
|
|
ftp.isc.org. 300 IN RRSIG A 13 3 300 (
|
|
20200401191851 20200302184340 27566 isc.org.
|
|
e9Vkb6/6aHMQk/t23Im71ioiDUhB06sncsduoW9+Asl4
|
|
L3TZtpLvZ5+zudTJC2coI4D/D9AXte1cD6FV6iS6PQ== )
|
|
|
|
;; Query time: 261 msec
|
|
;; SERVER: 10.53.0.1#53(10.53.0.1)
|
|
;; WHEN: Tue Mar 10 14:48:06 GMT 2020
|
|
;; MSG SIZE rcvd: 187
|
|
|
|
However, this time there is no ``ad`` flag in the header. Although
|
|
:iscman:`dig` is still returning the DNSSEC-related resource records, it is
|
|
not checking them, and thus cannot vouch for the authenticity of the answer.
|
|
If you do carry out this test, remember to re-enable DNSSEC validation
|
|
(by removing the ``dnssec-validation no;`` line from the configuration
|
|
file) before continuing.
|
|
|
|
.. _verifying_protection_from_bad_domains:
|
|
|
|
Verifying Protection From Bad Domain Names
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
It is also important to make sure that DNSSEC is protecting your network from
|
|
domain names that fail to validate; such failures could be caused by
|
|
attacks on your system, attempting to get it to accept false DNS
|
|
information. Validation could fail for a number of reasons: maybe the
|
|
answer doesn't verify because it's a spoofed response; maybe the
|
|
signature was a replayed network attack that has expired; or maybe the
|
|
child zone has been compromised along with its keys, and the parent
|
|
zone's information tells us that things don't add up. There is a
|
|
domain name specifically set up to fail DNSSEC validation,
|
|
``www.dnssec-failed.org``.
|
|
|
|
With DNSSEC validation enabled (the default), an attempt to look up that
|
|
name fails:
|
|
|
|
::
|
|
|
|
$ dig @10.53.0.1 www.dnssec-failed.org. A
|
|
|
|
; <<>> DiG 9.16.0 <<>> @10.53.0.1 www.dnssec-failed.org. A
|
|
; (1 server found)
|
|
;; global options: +cmd
|
|
;; Got answer:
|
|
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 22667
|
|
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
|
|
|
|
;; OPT PSEUDOSECTION:
|
|
; EDNS: version: 0, flags:; udp: 4096
|
|
; COOKIE: 69c3083144854587010000005e67bb57f5f90ff2688e455d (good)
|
|
;; QUESTION SECTION:
|
|
;www.dnssec-failed.org. IN A
|
|
|
|
;; Query time: 2763 msec
|
|
;; SERVER: 10.53.0.1#53(10.53.0.1)
|
|
;; WHEN: Tue Mar 10 16:07:51 GMT 2020
|
|
;; MSG SIZE rcvd: 78
|
|
|
|
On the other hand, if DNSSEC validation is disabled (by adding the
|
|
statement ``dnssec-validation no;`` to the :namedconf:ref:`options` clause in the
|
|
configuration file), the lookup succeeds:
|
|
|
|
::
|
|
|
|
$ dig @10.53.0.1 www.dnssec-failed.org. A
|
|
|
|
; <<>> DiG 9.16.0 <<>> @10.53.0.1 www.dnssec-failed.org. A
|
|
; (1 server found)
|
|
;; global options: +cmd
|
|
;; Got answer:
|
|
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54704
|
|
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
|
|
|
|
;; OPT PSEUDOSECTION:
|
|
; EDNS: version: 0, flags:; udp: 4096
|
|
; COOKIE: 251eee58208917f9010000005e67bb6829f6dabc5ae6b7b9 (good)
|
|
;; QUESTION SECTION:
|
|
;www.dnssec-failed.org. IN A
|
|
|
|
;; ANSWER SECTION:
|
|
www.dnssec-failed.org. 7200 IN A 68.87.109.242
|
|
www.dnssec-failed.org. 7200 IN A 69.252.193.191
|
|
|
|
;; Query time: 439 msec
|
|
;; SERVER: 10.53.0.1#53(10.53.0.1)
|
|
;; WHEN: Tue Mar 10 16:08:08 GMT 2020
|
|
;; MSG SIZE rcvd: 110
|
|
|
|
Do not be tempted to disable DNSSEC validation just because some names
|
|
are failing to resolve. Remember, DNSSEC protects your DNS lookup from
|
|
hacking. The next section describes how to quickly check whether
|
|
the failure to successfully look up a name is due to a validation
|
|
failure.
|
|
|
|
.. _how_do_i_know_validation_problem:
|
|
|
|
How Do I Know I Have a Validation Problem?
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Since all DNSSEC validation failures result in a general ``SERVFAIL``
|
|
message, how do we know if it was really a validation error?
|
|
Fortunately, there is a flag in :iscman:`dig`, ("CD" for "checking
|
|
disabled") which tells the server to disable DNSSEC validation. If
|
|
you receive a ``SERVFAIL`` message, re-run the query a second time
|
|
and set the :option:`dig +cd` flag. If the query succeeds with :option:`dig +cd`, but
|
|
ends in ``SERVFAIL`` without it, you know you are dealing with a
|
|
validation problem. So using the previous example of
|
|
``www.dnssec-failed.org`` and with DNSSEC validation enabled in the
|
|
resolver:
|
|
|
|
::
|
|
|
|
$ dig @10.53.0.1 www.dnssec-failed.org A +cd
|
|
|
|
; <<>> DiG 9.16.0 <<>> @10.53.0.1 www.dnssec-failed.org. A +cd
|
|
; (1 server found)
|
|
;; global options: +cmd
|
|
;; Got answer:
|
|
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62313
|
|
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
|
|
|
|
;; OPT PSEUDOSECTION:
|
|
; EDNS: version: 0, flags:; udp: 4096
|
|
; COOKIE: 73ca1be3a74dd2cf010000005e67c8c8e6df64b519cd87fd (good)
|
|
;; QUESTION SECTION:
|
|
;www.dnssec-failed.org. IN A
|
|
|
|
;; ANSWER SECTION:
|
|
www.dnssec-failed.org. 7197 IN A 68.87.109.242
|
|
www.dnssec-failed.org. 7197 IN A 69.252.193.191
|
|
|
|
;; Query time: 0 msec
|
|
;; SERVER: 10.53.0.1#53(10.53.0.1)
|
|
;; WHEN: Tue Mar 10 17:05:12 GMT 2020
|
|
;; MSG SIZE rcvd: 110
|
|
|
|
For more information on troubleshooting, please see
|
|
:ref:`dnssec_troubleshooting`.
|
|
|
|
.. _validation_easy_start_explained:
|
|
|
|
Validation Easy Start Explained
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
In :ref:`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 DNSSEC validation actually does, and some other options.
|
|
|
|
.. _dnssec_validation_explained:
|
|
|
|
:any:`dnssec-validation`
|
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
::
|
|
|
|
options {
|
|
dnssec-validation auto;
|
|
};
|
|
|
|
This “auto” line enables automatic DNSSEC trust anchor configuration
|
|
using the :any:`managed-keys` feature. In this case, no manual key
|
|
configuration is needed. There are three possible choices for the
|
|
:any:`dnssec-validation` option:
|
|
|
|
- *yes*: DNSSEC validation is enabled, but a trust anchor must be
|
|
manually configured. No validation actually takes place until
|
|
at least one trusted key has been manually configured.
|
|
|
|
- *no*: DNSSEC validation is disabled, and the recursive server behaves
|
|
in the "old-fashioned" way of performing insecure DNS lookups.
|
|
|
|
- *auto*: DNSSEC validation is enabled, and a default trust anchor
|
|
(included as part of BIND 9) for the DNS root zone is used. This is the
|
|
default; BIND automatically does this if there is no
|
|
:any:`dnssec-validation` line in the configuration file.
|
|
|
|
Let's discuss the difference between *yes* and *auto*. If set to
|
|
*yes*, the trust anchor must be manually defined and maintained
|
|
using the :any:`trust-anchors` statement (with either the ``static-key`` or
|
|
``static-ds`` modifier) in the configuration file; if set to
|
|
*auto* (the default, and as shown in the example), then no further
|
|
action should be required as BIND includes a copy [#root_zone_key_update]_ of the root key.
|
|
When set to *auto*, BIND automatically keeps the keys (also known as
|
|
trust anchors, discussed in :ref:`trust_anchors_description`)
|
|
up-to-date without intervention from the DNS administrator.
|
|
|
|
When using *yes*, please note that if :any:`trust-anchors` does not include a
|
|
valid root key, then validation does not take place for names which are not
|
|
covered by any of the configured trust anchors.
|
|
|
|
We recommend using the default *auto* unless there is a good reason to
|
|
require a manual trust anchor. To learn more about trust anchors,
|
|
please refer to :ref:`trusted_keys_and_managed_keys`.
|
|
|
|
.. _how_does_dnssec_change_dns_lookup_revisited:
|
|
|
|
How Does DNSSEC Change DNS Lookup (Revisited)?
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Now you've enabled validation on your recursive name server and
|
|
verified that it works. What exactly changed? In
|
|
:ref:`how_does_dnssec_change_dns_lookup` we looked at a very
|
|
high-level, simplified version of the 12 steps of the DNSSEC validation process. Let's revisit
|
|
that process now and see what your validating resolver is doing in more
|
|
detail. Again, as an example we are looking up the A record for the
|
|
domain name ``www.isc.org`` (see :ref:`dnssec_12_steps`):
|
|
|
|
1. The validating resolver queries the ``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.
|
|
|
|
2. Since the zone ``isc.org`` is signed, and its name servers are
|
|
DNSSEC-aware, it responds with the answer to the A record query plus
|
|
the RRSIG for the A record.
|
|
|
|
3. The validating resolver queries for the DNSKEY for ``isc.org``.
|
|
|
|
4. The ``isc.org`` name server responds with the DNSKEY and RRSIG
|
|
records. The DNSKEY is used to verify the answers received in #2.
|
|
|
|
5. The validating resolver queries the parent (``.org``) for the DS
|
|
record for ``isc.org``.
|
|
|
|
6. The ``.org`` name server is also DNSSEC-aware, so it responds with the
|
|
DS and RRSIG records. The DS record is used to verify the answers
|
|
received in #4.
|
|
|
|
7. The validating resolver queries for the DNSKEY for ``.org``.
|
|
|
|
8. The ``.org`` name server responds with its DNSKEY and RRSIG. The DNSKEY
|
|
is used to verify the answers received in #6.
|
|
|
|
9. The validating resolver queries the parent (root) for the DS record
|
|
for ``.org``.
|
|
|
|
10. The root name server, being DNSSEC-aware, responds with DS and RRSIG
|
|
records. The DS record is used to verify the answers received in #8.
|
|
|
|
11. The validating resolver queries for the DNSKEY for root.
|
|
|
|
12. The root name server responds with its DNSKEY and RRSIG. The DNSKEY is
|
|
used to verify the answers received in #10.
|
|
|
|
After step #12, the validating resolver takes the DNSKEY received and
|
|
compares it to the key or keys it has configured, to decide whether
|
|
the received key can be trusted. We talk about these locally
|
|
configured keys, or trust anchors, in :ref:`trust_anchors_description`.
|
|
|
|
With DNSSEC, every response includes not just the
|
|
answer, but a digital signature (RRSIG) as well, so the
|
|
validating resolver can verify the answer received. That is what we
|
|
look at in the next section, :ref:`how_are_answers_verified`.
|
|
|
|
.. _how_are_answers_verified:
|
|
|
|
How Are Answers Verified?
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
.. note::
|
|
|
|
Keep in mind, as you read this section, that although words like
|
|
"encryption" and "decryption"
|
|
are used here from time to time, DNSSEC does not provide privacy.
|
|
Public key cryptography is used to verify data *authenticity* (who
|
|
sent it) and data *integrity* (it did not change during transit), but
|
|
any eavesdropper can still see DNS requests and responses in
|
|
clear text, even when DNSSEC is enabled.
|
|
|
|
So how exactly are DNSSEC answers 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, and this hashed value is then encrypted by a
|
|
private key. This encrypted hash value is the digital signature.
|
|
|
|
.. figure:: ../dnssec-guide/img/signature-generation.png
|
|
:alt: Signature Generation
|
|
:width: 80.0%
|
|
|
|
Signature Generation
|
|
|
|
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 (it is 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, which we'll call
|
|
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,
|
|
which we'll call 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 this answer came from the authoritative server
|
|
(authenticity), and the content remained intact during transit
|
|
(integrity).
|
|
|
|
.. figure:: ../dnssec-guide/img/signature-verification.png
|
|
:alt: Signature Verification
|
|
:width: 80.0%
|
|
|
|
Signature Verification
|
|
|
|
Take the A record ``ftp.isc.org``, for example. The plain text is:
|
|
|
|
::
|
|
|
|
ftp.isc.org. 4 IN A 149.20.1.49
|
|
|
|
The digital signature portion is:
|
|
|
|
::
|
|
|
|
ftp.isc.org. 300 IN RRSIG A 13 3 300 (
|
|
20200401191851 20200302184340 27566 isc.org.
|
|
e9Vkb6/6aHMQk/t23Im71ioiDUhB06sncsduoW9+Asl4
|
|
L3TZtpLvZ5+zudTJC2coI4D/D9AXte1cD6FV6iS6PQ== )
|
|
|
|
When a validating resolver queries for the A record ``ftp.isc.org``, it
|
|
receives both the A record and the RRSIG record. It runs the A record
|
|
through a hash function (in this example, SHA256 as
|
|
indicated by the number 13, signifying ECDSAP256SHA256) 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? Look
|
|
at the two timestamps in our example above:
|
|
|
|
- Signature Expiration: 20200401191851
|
|
|
|
- Signature Inception: 20200302184340
|
|
|
|
This tells us that this signature was generated UTC March 2nd, 2020, at
|
|
6:43:40 PM (20200302184340), and it is good until UTC April 1st, 2020,
|
|
7:18:51 PM (20200401191851). The validating resolver's current
|
|
system time needs to fall between these two timestamps. If it does not, 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 the hash value check and the timestamp check, it is
|
|
validated and the authenticated data (``ad``) bit is set, and the response
|
|
is sent to the client; if it does not verify, a SERVFAIL is returned to
|
|
the client.
|
|
|
|
.. _trust_anchors_description:
|
|
|
|
Trust Anchors
|
|
~~~~~~~~~~~~~
|
|
|
|
A trust anchor is a key that is placed into a validating resolver, so
|
|
that the validator can verify the results of a given request with a
|
|
known or trusted public key (the trust anchor). A validating resolver
|
|
must have at least one trust anchor installed to perform DNSSEC
|
|
validation.
|
|
|
|
.. _how_trust_anchors_are_used:
|
|
|
|
How Trust Anchors are Used
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
In the section :ref:`how_does_dnssec_change_dns_lookup_revisited`,
|
|
we walked through the 12 steps of the DNSSEC lookup process. At the end
|
|
of the 12 steps, a critical comparison happens: the key received from
|
|
the remote server and the key we have on file are compared to see if we
|
|
trust it. The key we have on file is called a trust anchor, sometimes
|
|
also known as a trust key, trust point, or secure entry point.
|
|
|
|
The 12-step lookup process describes the DNSSEC lookup in the ideal
|
|
world, where every single domain name is signed and properly delegated,
|
|
and where each validating resolver only needs to have one trust anchor - that
|
|
is, the root's public key. But there is no restriction that the
|
|
validating resolver must only have one trust anchor. In fact, in the
|
|
early stages of DNSSEC adoption, it was not unusual for a validating
|
|
resolver to have more than one trust anchor.
|
|
|
|
For instance, before the root zone was signed (in July 2010), some
|
|
validating resolvers that wished to validate domain names in the ``.gov``
|
|
zone needed to obtain and install the key for ``.gov``. A sample lookup
|
|
process for ``www.fbi.gov`` at that time would have been eight steps rather
|
|
than 12:
|
|
|
|
.. figure:: ../dnssec-guide/img/dnssec-8-steps.png
|
|
:alt: DNSSEC Validation with ``.gov`` Trust Anchor
|
|
|
|
|
|
1. The validating resolver queried ``fbi.gov`` name server for the A
|
|
record of ``www.fbi.gov``.
|
|
|
|
2. The FBI's name server responded with the answer and its RRSIG.
|
|
|
|
3. The validating resolver queried the FBI's name server for its DNSKEY.
|
|
|
|
4. The FBI's name server responded with the DNSKEY and its RRSIG.
|
|
|
|
5. The validating resolver queried a ``.gov`` name server for the DS
|
|
record of ``fbi.gov``.
|
|
|
|
6. The ``.gov`` name server responded with the DS record and the
|
|
associated RRSIG for ``fbi.gov``.
|
|
|
|
7. The validating resolver queried the ``.gov`` name server for its DNSKEY.
|
|
|
|
8. The ``.gov`` name server responded with its DNSKEY and the associated
|
|
RRSIG.
|
|
|
|
This all looks very similar, except it's shorter than the 12 steps that
|
|
we saw earlier. Once the validating resolver receives the DNSKEY file in
|
|
#8, it recognizes that this is the manually configured trusted key
|
|
(trust anchor), and never goes to the root name servers to ask for the
|
|
DS record for ``.gov``, or ask the root name servers for their DNSKEY.
|
|
|
|
In fact, whenever the validating resolver receives a DNSKEY, it checks
|
|
to see if this is a configured trusted key to decide whether it
|
|
needs to continue chasing down the validation chain.
|
|
|
|
.. _trusted_keys_and_managed_keys:
|
|
|
|
Trusted Keys and Managed Keys
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Since the resolver is validating, we must have at least one key (trust
|
|
anchor) configured. How did it get here, and how do we maintain it?
|
|
|
|
If you followed the recommendation in
|
|
:ref:`easy_start_guide_for_recursive_servers`, by setting
|
|
:any:`dnssec-validation` to *auto*, there is nothing left to do.
|
|
BIND already includes a copy of the root key, and automatically updates it
|
|
when the root key changes. [#root_zone_key_update]_ It looks something like this:
|
|
|
|
::
|
|
|
|
trust-anchors {
|
|
# This key (20326) was published in the root zone in 2017.
|
|
. initial-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3
|
|
+/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv
|
|
ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF
|
|
0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e
|
|
oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd
|
|
RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN
|
|
R1AkUTV74bU=";
|
|
};
|
|
|
|
You can, of course, decide to manage this key manually yourself.
|
|
First, you need to make sure that :any:`dnssec-validation` is set
|
|
to *yes* rather than *auto*:
|
|
|
|
::
|
|
|
|
options {
|
|
dnssec-validation yes;
|
|
};
|
|
|
|
Then, download the root key manually from a trustworthy source,
|
|
and put it into a :any:`trust-anchors` statement as shown below:
|
|
|
|
::
|
|
|
|
trust-anchors {
|
|
# This key (20326) was published in the root zone in 2017.
|
|
. static-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3
|
|
+/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv
|
|
ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF
|
|
0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e
|
|
oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd
|
|
RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN
|
|
R1AkUTV74bU=";
|
|
};
|
|
|
|
While this :any:`trust-anchors` statement looks similar to the built-in
|
|
version above, the built-in key has the ``initial-key`` modifier, whereas
|
|
in the statement in the configuration file, that is replaced by
|
|
``static-key``. There is an important difference between the two: a key
|
|
defined with ``static-key`` is always trusted until it is deleted from the
|
|
configuration file. With the ``initial-key`` modifier, keys are only
|
|
trusted once: for as long as it takes to load the managed key database and
|
|
start the key maintenance process. Thereafter, BIND uses the managed keys
|
|
database (``managed-keys.bind.jnl``) as the source of key information.
|
|
|
|
.. warning::
|
|
|
|
Remember, if you choose to manage the keys on your own, whenever the
|
|
key changes (which, for most zones, happens on a periodic basis),
|
|
the configuration needs to be updated manually. Failure to do so will
|
|
result in breaking nearly all DNS queries for the subdomain of the
|
|
key. So if you are manually managing ``.gov``, all domain names in
|
|
the ``.gov`` space may become unresolvable; if you are manually
|
|
managing the root key, you could break all DNS requests made to your
|
|
recursive name server.
|
|
|
|
Explicit management of keys was common in the early days of DNSSEC, when
|
|
neither the root zone nor many top-level domains were signed. Since
|
|
then, `over 90% <https://ithi.research.icann.org/graph-m7.html>`__ of
|
|
the top-level domains have been signed, including all the largest ones.
|
|
Unless you have a particular need to manage keys yourself, it is best to
|
|
use the BIND defaults and let the software manage the root key.
|
|
|
|
.. [#root_zone_key_update]
|
|
The root zone was signed in July 2010 and, as at the time of this writing
|
|
(mid-2020), the key has been changed once, in October 2018. The intention going
|
|
forward is to roll the key once every five years.
|
|
|
|
.. _whats_edns0_all_about:
|
|
|
|
What's EDNS All About (And Why Should I Care)?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. _whats-edns0-all-about-overview:
|
|
|
|
EDNS Overview
|
|
^^^^^^^^^^^^^
|
|
|
|
Traditional DNS responses are typically small in size (less than 512
|
|
bytes) and fit nicely into a small UDP packet. The Extension mechanism
|
|
for DNS (EDNS, or EDNS(0)) offers a mechanism to send DNS data in
|
|
larger packets over UDP. To support EDNS, both the DNS server
|
|
and the network need to be properly prepared to support the larger
|
|
packet sizes and multiple fragments.
|
|
|
|
This is important for DNSSEC, since the :option:`dig +do` bit that signals
|
|
DNSSEC-awareness is carried within EDNS, and DNSSEC responses are larger
|
|
than traditional DNS ones. If DNS servers and the network environment cannot
|
|
support large UDP packets, it will cause retransmission over TCP, or the
|
|
larger UDP responses will be discarded. Users will likely experience
|
|
slow DNS resolution or be unable to resolve certain names at all.
|
|
|
|
Note that EDNS applies regardless of whether you are validating DNSSEC, because
|
|
BIND has DNSSEC enabled by default.
|
|
|
|
Please see :ref:`network_requirements` for more information on what
|
|
DNSSEC expects from the network environment.
|
|
|
|
.. _edns_on_dns_servers:
|
|
|
|
EDNS on DNS Servers
|
|
^^^^^^^^^^^^^^^^^^^
|
|
|
|
For many years, BIND has had EDNS enabled by default,
|
|
and the UDP packet size is set to a maximum of 4096 bytes. The DNS
|
|
administrator should not need to perform any reconfiguration. You can
|
|
use :iscman:`dig` to verify that your server supports EDNS and see the UDP packet
|
|
size it allows with this :iscman:`dig` command:
|
|
|
|
::
|
|
|
|
$ dig @10.53.0.1 www.isc.org. A +dnssec +multiline
|
|
|
|
; <<>> DiG 9.16.0 <<>> @10.53.0.1 ftp.isc.org a +dnssec +multiline
|
|
; (1 server found)
|
|
;; global options: +cmd
|
|
;; Got answer:
|
|
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48742
|
|
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
|
|
|
|
;; OPT PSEUDOSECTION:
|
|
; EDNS: version: 0, flags: do; udp: 4096
|
|
; COOKIE: 29a9705c2160b08c010000005e67a4a102b9ae079c1b24c8 (good)
|
|
;; QUESTION SECTION:
|
|
;ftp.isc.org. IN A
|
|
|
|
;; ANSWER SECTION:
|
|
ftp.isc.org. 300 IN A 149.20.1.49
|
|
ftp.isc.org. 300 IN RRSIG A 13 3 300 (
|
|
20200401191851 20200302184340 27566 isc.org.
|
|
e9Vkb6/6aHMQk/t23Im71ioiDUhB06sncsduoW9+Asl4
|
|
L3TZtpLvZ5+zudTJC2coI4D/D9AXte1cD6FV6iS6PQ== )
|
|
|
|
;; Query time: 452 msec
|
|
;; SERVER: 10.53.0.1#53(10.53.0.1)
|
|
;; WHEN: Tue Mar 10 14:30:57 GMT 2020
|
|
;; MSG SIZE rcvd: 187
|
|
|
|
There is a helpful testing tool available (provided by DNS-OARC) that
|
|
you can use to verify resolver behavior regarding EDNS support:
|
|
`<https://www.dns-oarc.net/oarc/services/replysizetest/>`__ .
|
|
|
|
Once you've verified that your name servers have EDNS enabled, that should be the
|
|
end of the story, right? Unfortunately, EDNS is a hop-by-hop extension
|
|
to DNS. This means the use of EDNS is negotiated between each pair of
|
|
hosts in a DNS resolution process, which in turn means if one of your
|
|
upstream name servers (for instance, your ISP's recursive name server
|
|
that your name server forwards to) does not support EDNS, you may experience DNS
|
|
lookup failures or be unable to perform DNSSEC validation.
|
|
|
|
.. _support_for_large_packets_network_equipment:
|
|
|
|
Support for Large Packets on Network Equipment
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
If both your recursive name server and your ISP's name servers
|
|
support EDNS, we are all good here, right? Not so fast. Since these large
|
|
packets have to traverse the network, the network infrastructure
|
|
itself must allow them to pass.
|
|
|
|
When data is physically transmitted over a network, it has to be broken
|
|
down into chunks. The size of the data chunk is known as the Maximum
|
|
Transmission Unit (MTU), and it can differ from network to
|
|
network. IP fragmentation occurs when a large data packet needs to be
|
|
broken down into chunks smaller than the
|
|
MTU; these smaller chunks then need to be reassembled back into the large
|
|
data packet at their destination. IP fragmentation is not necessarily a bad thing, and it most
|
|
likely occurs on your network today.
|
|
|
|
Some network equipment, such as a firewall, may make assumptions about
|
|
DNS traffic. One of these assumptions may be how large each DNS packet
|
|
is. When a firewall sees a larger DNS packet than it expects, it may either
|
|
reject the large packet or drop its fragments because the firewall
|
|
thinks it's an attack. This configuration probably didn't cause problems
|
|
in the past, since traditional DNS packets are usually pretty small in
|
|
size. However, with DNSSEC, these configurations need to be updated,
|
|
since DNSSEC traffic regularly exceeds 1500 bytes (a common MTU value).
|
|
If the configuration is not updated to support a larger DNS packet size,
|
|
it often results in the larger packets being rejected, and to the
|
|
end user it looks like the queries go unanswered. Or in the case of
|
|
fragmentation, only a part of the answer makes it to the validating
|
|
resolver, and your validating resolver may need to re-ask the question
|
|
again and again, creating the appearance for end users that the DNS/network is slow.
|
|
|
|
While you are updating the configuration on your network equipment, make
|
|
sure TCP port 53 is also allowed for DNS traffic.
|
|
|
|
.. _dns_uses_tcp:
|
|
|
|
Wait... DNS Uses TCP?
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Yes. DNS uses TCP port 53 as a fallback mechanism, when it cannot use
|
|
UDP to transmit data. This has always been the case, even long before
|
|
the arrival of DNSSEC. Traditional DNS relies on TCP port 53 for
|
|
operations such as zone transfer. The use of DNSSEC, or DNS with IPv6
|
|
records such as AAAA, increases the chance that DNS data will be
|
|
transmitted via TCP.
|
|
|
|
Due to the increased packet size, DNSSEC may fall back to TCP more often
|
|
than traditional (insecure) DNS. If your network blocks or
|
|
filters TCP port 53 today, you may already experience instability with
|
|
DNS resolution, before even deploying DNSSEC.
|