This document lists categorized answers and questions with links to the relevant documentation.
You may have spotted the 512 in something like the following (after EDNS ... udp:
):
$ dig example.com @127.0.0.1
; <<>> DiG 9.11.5-P4-5.1+deb10u3-Debian <<>> example.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20155
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 43200 IN A 93.184.216.34
;; Query time: 86 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Apr 15 13:56:34 CEST 2021
;; MSG SIZE rcvd: 56
and wonder ‘why is the Recursor using a bufsize of 512? Did we not decide on a Flag Day, all together, that we would use 1232?’
The EDNS buffer size in a DNS packet, generated by side A, tells the recipient of that packet (side B) the maximum packet size that side A will accept from side B. So, when the Recursor talks to an Authoritative, the Recursor reports the buffer size the Authoritative is allowed to use to it - usually 1232 (edns-outgoing-bufsize). But the example above is the Recursor responding to a client, and it is telling the client ‘from you, I accept packets of up to 512 bytes’. Or, to say it differently, the Recursor is telling the client that questions must fit in 512 bytes. This is fine for the Recursor - unlike an Authoritative, that might need to handle big UPDATE requests, the Recursor really only answers simple questions from clients, and those always comfortably fit in 512 bytes, because the maximum length of a DNS name is 256 bytes.
Similarly, the maximum size of a response from the Recursor to a client is governed by the buffer size sent by the client (in dig
, you can see that number by doing dig +qr
), and the udp-truncation-threshold setting in the Recursor configuration.
To see the buffer size the Recursor is sending to authoritatives, you can ask the question below, which gets sent to an authoritative server reporting in a TXT answer record what it saw in the query:
$ dig txt header.lua.powerdns.org +short @127.0.0.1
"id: 52938, aa: false, rd: false, ad: false, cd: false, do: true, ednsbufsiz: 1232, tcp: false"
Or, in a diagram:
udp-truncation-threshold edns-outgoing-bufsize
[default is 1232] [default is 1232]
| |
+------+ v +----------+ v +------------+
| stub | <=========> | recursor | <===================> | responders |
+------+ +----------+ +------------+
^
|
client bufsize (stub => recursor)
bufsize reported to client (recursor => stub [always 512])
On startup, the Recursor uses root hints to resolve the names and addresses of the root name servers and puts the record sets found into the record cache. This is needed to be able to resolve names, as the recursive algorithm starts at the root (using cached data) and then tries to resolve delegations until it finds the name servers that are authoritative for the domain in question.
If the hint-file is not set, Recursor wil use a compiled-in table as root hints.
Periodically, based on the max-cache-ttl, the Recursor will refetch the root data using data in its cache by doing a . NS query. If that does not succeed, it will fall back to using the root hints to fill the cache with root data. Prior to version 4.7.0, the period for re-fetching root data was max-cache-ttl divided by 12, with a minimum of 10 seconds. Starting with version 4.7.0, the period is adaptive, starting at 80% of max-cache-ttl, reducing the interval on failure.
The root hints and resolved root data can differ if the root hints are outdated. As long as at least one root server mentioned in the root hints can be contacted, the periodic refresh will produce the desired record sets corresponding to the current up-to-date root server data.
Starting with version 4.6.2, if hint-file is set to no
, the Recursor will not prime the cache with root data obtained from hints, but will still do the periodic refresh.
A (recursive) forward configuration is needed to make the periodic refresh work.
Starting with version 4.9, setting hint-file to no-refresh
disables both the initial reading of the hints and the periodic refresh of cached root data.
This prevents Recursor from resolving names by itself, so it is only useful in cases where all queries are forwarded.
With versions older than 4.8, there is another detail: after refreshing the root records, the Recursor will resolve the NS
records for the top level domain of the root servers.
For example, in the default setup the root name servers are called [a-m].root-servers.net
, so the Recursor will resolve the name servers of the .net
domain.
This is needed to correctly determine zone cuts to be able to decide if the .root-servers.net
domain is DNSSEC protected. Newer versions solve this by querying the needed information top-down.
Starting with version 5.0.0, enabling allow-no-rd allows for queries without the recursion desired bit to be answered from cache.
Older versions of the dig
program provided by ISC do not set the RD bit on the initial +trace
query causing it to sometimes fail to perform a +trace
when asking a freshly restarted Recursor despite the allow-no-rd option being set.
This is because there is a short while after restarting that the cache has no authoritative data on the root, so it will answer with an NODATA (NOERROR and no answer records) in that period for RD=0 queries asking for the root name servers.
For dig
this has been fixed in BIND 9.15.1 by setting the RD bit.