dig +trace should not set RD=0 (+norecurse) for the initial root hints query
When running, e.g., dig +trace gitlab.isc.org
, recursion is automatically disabled. This is documented in the manual page:
+[no]recurse
Toggle the setting of the RD (recursion desired) bit in the query.
This bit is set by default, which means dig normally sends
recursive queries. Recursion is automatically disabled when the
+nssearch or +trace query options are used.
This makes perfect sense, except for the initial query for the NS records of the .
root zone.
Setting RD=0
in the initial IN NS .
query prevents dig +trace
from functioning correctly when the configured upstream nameserver of the system (e.g., the nameserver
line(s) found in /etc/resolv.conf
on Linux systems) is a DNS forwarder/proxy - because it will refuse to answer the query.
This example shows this happening on a modern Linux system (Fedora 30) using the systemd-resolved
DNS forwarder:
$ ./dig +trace gitlab.isc.org.
; <<>> DiG 9.15.0 <<>> +trace gitlab.isc.org.
;; global options: +cmd
;; Received 51 bytes from 127.0.0.53#53(127.0.0.53) in 0 ms
$ ./dig . IN NS +norecurse
; <<>> DiG 9.15.0 <<>> . IN NS +norecurse
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 35753
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;. IN NS
;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: må. mai 13 20:56:57 CEST 2019
;; MSG SIZE rcvd: 28
When querying for the root hints with RD=1
, the desired answer is given:
$ ./dig . IN NS +recurse
; <<>> DiG 9.15.0 <<>> . IN NS
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49484
;; flags: qr rd ra; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;. IN NS
;; ANSWER SECTION:
. 81613 IN NS b.root-servers.net.
. 81613 IN NS d.root-servers.net.
. 81613 IN NS f.root-servers.net.
. 81613 IN NS a.root-servers.net.
. 81613 IN NS k.root-servers.net.
. 81613 IN NS c.root-servers.net.
. 81613 IN NS j.root-servers.net.
. 81613 IN NS i.root-servers.net.
. 81613 IN NS m.root-servers.net.
. 81613 IN NS l.root-servers.net.
. 81613 IN NS h.root-servers.net.
. 81613 IN NS g.root-servers.net.
. 81613 IN NS e.root-servers.net.
;; Query time: 138 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: må. mai 13 20:57:00 CEST 2019
;; MSG SIZE rcvd: 239
As I understand it, the DNS forwarder correctly implements the DNS protocol when it answers this query with REFUSED
.
This understanding is based on the following specification from RFC 8499:
Non-recursive query: A query with the Recursion Desired (RD) bit set
to 0 in the header. A server can answer non-recursive queries
using only local information: the response contains either an
error, the answer, or a referral to some other server "closer" to
the answer. (See Section 4.3.1 of [RFC1034].)
Since the forwarder does not contain a built-in root hints zone file, it simply cannot «answer [dig +trace's] no-recursive queries using only local information»; thus answering with a REFUSED
error is the only real option: it does not have the answer, nor would it be possible to give a «a referral to some other server "closer" to the answer» (at least I cannot imagine how such a referral would look like).
I therefore propose that the dig
tool delays setting +norecurse
/RD=0
until the second query, i.e., after the root hints have been obtained.