Recursive Resolver
Hickory supports the role of a Recursive Resolver. A recursive resolver is a DNS server that accepts recursive queries and is able to resolve these queries by fetching additional records from other known authoritative name servers or from its cache. A recursive resolver can validate the recursive query to answer the question if the chain of trust is valid.
Configuration
To run Hickory as a recursive resolver with DNSSEC validation the following steps are necessary:
- create a root hints file named
root.hints
- create a trust anchor file named
trusted-key.key
- configure Hickory via
config.toml
Root Hints
The root hints file is used to define a set of authoritative name servers Hickory can query to fetch records for which
it has no authority over. For example the Internet Assigned Numbers Authority (IANA)
provides a set of files for their root name servers (see here). IANA is the authority
for the root zone "."
, they are responsible for assigning operators for top level domains (e.g. com
, de
).
For our example we will use the root.hints
file provided by IANA and copy that to a local file.
Trust Anchor
In order to validate the chain of records successfully Hickory needs the trust anchor for the root zone "."
.
The keys can be fetched via dig
.
dig DNSKEY . +answer
The command returns two DNSKEY
records (abbreviated) in the ANSWERS
section of the response:
. 19347 IN DNSKEY 256 3 8 AwEAAc0SunbHdS0KFEyZbYII/+tzsrNzIwurKxmJA+0fhAYlTPA/5LrM ...
. 19347 IN DNSKEY 257 3 8 AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 ...
Create a new file named trusted-key.key
, copy the content of the ANSWERS
section into it. These keys are involved
in the validation of the root zone.
config.toml
The last step is to configure Hickory as a recursive resolver.
# config.toml
[[zones]]
zone = "."
zone_type = "Hint"
stores = { type = "recursor", roots = "/absolute/path/root.hints", dnssec_policy.ValidateWithStaticKey.path = "/absolute/path/trusted-key.key" }
The configuration consists of the following fields:
zone
- The zone to configure.zone_type
- TheHint
value indicates a zone with recursive resolver abilities.stores
- A block that defines a store type.type
- Indicates arecursor
configurationroots
- The file path to the root hints file.dnssec_policy
- Configues the DNSSEC validation policy.ValidateWithStaticKey.path
- The file path to the trusted key used for DNSSEC validation.
Note: Both path fields,
root
andValidateWithStaticKey.path
, need to be absolute paths.
Run Hickory
To start Hickory run:
hickory-dns --port 2345 --debug --config=./config.toml
This runs the DNS server on port 2345
with the resolver configuration. This time the DNS server
can forward requests to the root name servers specified in the root.hints
file.
DNSSEC Validation
Hickory started as recursive resolver and will execute DNSSEC validation for a query.
Using dig
In order to answer a recursive query the client needs to send
the RD
(Recursion Desired) flag.
Using dig
we can see that for an existing domain no records will be returned if the flag is disabled.
dig @127.0.0.1 -p 2345 example.com. +norecurse
This is because the recursive resolver cannot answer this query on its own.
By setting the RD
flag in dig
(default) the query will return the A
record for domain example.com
.
The command
dig @127.0.0.1 -p 2345 example.com. +recurse
returns
; <<>> DiG 9.20.2 <<>> @127.0.0.1 -p 2345 example.com. +recurse
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30300
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
; OPT=5: 08 0d 0e 0f ("....")
; OPT=6: 08 0d 0e 0f ("....")
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 3600 IN A 93.184.215.14
;; Query time: 851 msec
;; SERVER: 127.0.0.1#2345(127.0.0.1) (UDP)
;; WHEN: Tue Oct 22 11:09:47 CEST 2024
;; MSG SIZE rcvd: 83
Specifiying the +dnssec
option in the dig
command will additionally return the RRSIG
record.
Check the hickory-dns
log to learn how the recursive query is processed, the DNSSEC validation, and what
other name servers were involved.
The recursive resolver performs DNSSEC validation for each client query to validate the chain of trust.
This validates all records that are involved in the query resolution, and returns the appropriate response.
The DNS server automatically sets the ad
flag
(Authentic Data) in its response to indicate successful validation.
To return all records even when DNSSEC validation fails set the checking disabled
flag CD
using dig
's +cdflag
option.
For example the following query uses dig
to fetch the A
record for a domain that fails DNSSEC validation:
dig @127.0.0.1 -p 2345 www.dnssec-failed.org. +dnssec +cdflag
Without the +cdflag
the query would not return any records. The flags
field in the answer will not contain the
authenticated data (AD) bit to indicate there was a problem with the DNSSEC validation.
Using delv
Another tool to query DNS servers is delv
. It can be used to return more information on the
DNSSEC validation process. Let's try the same query as above using delv
:
delv @127.0.0.1 -p 2345 example.com. A
returns
; fully validated
example.com. 3447 IN A 93.184.215.14
example.com. 3447 IN RRSIG A 13 2 3600 20241102170341 20241012065317 19367 example.com. XMyTWC8y9WecF5ST67DyRUK3Ptvfpy/+Oetha9r6ZU0RJ4aclvY32uKC ojUsjCUHaejma032va/7Z4Yd3Krq8Q==
The important line here is ; fully validated
, the remainig output is similar to dig
, the returned records are the same.
Let's query a record for a domain that does not exist.
delv @127.0.0.1 -p 2345 doesnotexist.com. A
returns
;; no valid RRSIG resolving 'doesnotexist.com/DS/IN': 127.0.0.1#2345
;; broken trust chain resolving 'doesnotexist.com/A/IN': 127.0.0.1#2345
;; resolution failed: broken trust chain
This is a good start, but it doesn't really provide the full picture of what's happening under the hood. To figure
out more about the validation process either check the output of hickory-dns
or alternatively display the
intermediate steps using delv
as well.
To display a brief list of validation steps use the +rtrace
option:
delv @127.0.0.1 -p 2345 example.com. A +rtrace
that ouputs
;; fetch: example.com/A
;; fetch: example.com/DNSKEY
;; fetch: example.com/DS
;; fetch: com/DNSKEY
;; fetch: com/DS
;; fetch: ./DNSKEY
; fully validated
example.com. 2641 IN A 93.184.215.14
example.com. 2641 IN RRSIG A 13 2 3600 20241102170341 20241012065317 19367 example.com. ...
The query returns information on intermediate steps, with the chain of trust fully validated.
To get the full picture including all intermediate DNS queries and responses use the +mtrace
option
delv @127.0.0.1 -p 2345 example.com. A +mtrace