NLnetLabs / nsd

The NLnet Labs Name Server Daemon (NSD) is an authoritative, RFC compliant DNS nameserver.
https://nlnetlabs.nl/nsd
BSD 3-Clause "New" or "Revised" License
462 stars 104 forks source link

NSD returns 3 NSEC3 records for NODATA response #190

Closed anandb-ripencc closed 3 years ago

anandb-ripencc commented 3 years ago

While debugging queries for ira.go.ug/DS, I have noticed that NSD returns 3 NSEC3 records in the authority section. I don't believe the extra NSEC3 record causes any harm. However, operationally, it has a consequence, which is a bigger response, compared to say BIND or Knot DNS. If an NSD server limits the UDP buffer size to 1232 (as is the recommendation these days), it causes truncation, and the client tries again over TCP. Compare the following responses:

NSD with 4096-byte buffer size:

; <<>> DiG 9.16.20 <<>> +norec +dnssec ira.go.ug ds @ns.icann.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14066
;; flags: qr aa; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;ira.go.ug.         IN  DS

;; AUTHORITY SECTION:
ug.         14400   IN  SOA root.eahd.or.ug. servers.i3c.co.ug. 2017250138 86400 3600 2592000 14400
ug.         14400   IN  RRSIG   SOA 8 1 14400 20210923210000 20210814210000 63693 ug. [omitted]
8r4475uh5oosjqhv6dhdmccf6mllupgv.ug. 14400 IN NSEC3 1 1 10 799D670A 90U6TO1ODSNCOIFUT34IFNPP1IECC15L NS SOA RRSIG DNSKEY NSEC3PARAM
8r4475uh5oosjqhv6dhdmccf6mllupgv.ug. 14400 IN RRSIG NSEC3 8 2 14400 20210923210000 20210814210000 63693 ug. [omitted]
dpk1ca38i2bp09sfh57ishifd8ebi04s.ug. 14400 IN NSEC3 1 1 10 799D670A IA8GCNUUS76RKVEMFSB6O4KQ09S1I5CS NS DS RRSIG
dpk1ca38i2bp09sfh57ishifd8ebi04s.ug. 14400 IN RRSIG NSEC3 8 2 14400 20210923210000 20210814210000 63693 ug. [omitted]
qk9e3k4slop401t887vvsnna8lq2fjbs.ug. 14400 IN NSEC3 1 1 10 799D670A SS5UP489HPGNTUTRSH295N0AGS13GJ08 NS DS RRSIG
qk9e3k4slop401t887vvsnna8lq2fjbs.ug. 14400 IN RRSIG NSEC3 8 2 14400 20210923210000 20210814210000 63693 ug. [omitted]

NSD with 1232-byte buffer:

;; Truncated, retrying in TCP mode.

; <<>> DiG 9.16.20 <<>> +norec +dnssec +nsid ira.go.ug ds @ns-ug.afrinic.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64509
;; flags: qr aa; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
; NSID: 73 30 34 2d 6e 73 32 2e 6a 6e 62 ("s04-ns2.jnb")
;; QUESTION SECTION:
;ira.go.ug.         IN  DS

;; AUTHORITY SECTION:
ug.         14400   IN  SOA root.eahd.or.ug. servers.i3c.co.ug. 2017250135 86400 3600 2592000 14400
ug.         14400   IN  RRSIG   SOA 8 1 14400 20210923210000 20210814210000 63693 ug. [omitted]
8r4475uh5oosjqhv6dhdmccf6mllupgv.ug. 14400 IN NSEC3 1 1 10 799D670A 90U6TO1ODSNCOIFUT34IFNPP1IECC15L NS SOA RRSIG DNSKEY NSEC3PARAM
8r4475uh5oosjqhv6dhdmccf6mllupgv.ug. 14400 IN RRSIG NSEC3 8 2 14400 20210923210000 20210814210000 63693 ug. [omitted]
dpk1ca38i2bp09sfh57ishifd8ebi04s.ug. 14400 IN NSEC3 1 1 10 799D670A IA8GCNUUS76RKVEMFSB6O4KQ09S1I5CS NS DS RRSIG
dpk1ca38i2bp09sfh57ishifd8ebi04s.ug. 14400 IN RRSIG NSEC3 8 2 14400 20210923210000 20210814210000 63693 ug. [omitted]
qk9e3k4slop401t887vvsnna8lq2fjbs.ug. 14400 IN NSEC3 1 1 10 799D670A SS5UP489HPGNTUTRSH295N0AGS13GJ08 NS DS RRSIG
qk9e3k4slop401t887vvsnna8lq2fjbs.ug. 14400 IN RRSIG NSEC3 8 2 14400 20210923210000 20210814210000 63693 ug. [omitted]

And a BIND server:

; <<>> DiG 9.16.20 <<>> +norec +dnssec +nsid ira.go.ug ds @root.eahd.or.ug
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10510
;; flags: qr aa; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;ira.go.ug.         IN  DS

;; AUTHORITY SECTION:
8R4475UH5OOSJQHV6DHDMCCF6MLLUPGV.ug. 14400 IN NSEC3 1 1 10 799D670A 90U6TO1ODSNCOIFUT34IFNPP1IECC15L NS SOA RRSIG DNSKEY NSEC3PARAM
8R4475UH5OOSJQHV6DHDMCCF6MLLUPGV.ug. 14400 IN RRSIG NSEC3 8 2 14400 20210923210000 20210814210000 63693 ug. [omitted]
ug.         14400   IN  SOA root.eahd.or.ug. servers.i3c.co.ug. 2017250138 86400 3600 2592000 14400
ug.         14400   IN  RRSIG   SOA 8 1 14400 20210923210000 20210814210000 63693 ug. [omitted]
DPK1CA38I2BP09SFH57ISHIFD8EBI04S.ug. 14400 IN NSEC3 1 1 10 799D670A IA8GCNUUS76RKVEMFSB6O4KQ09S1I5CS NS DS RRSIG
DPK1CA38I2BP09SFH57ISHIFD8EBI04S.ug. 14400 IN RRSIG NSEC3 8 2 14400 20210923210000 20210814210000 63693 ug. [omitted]
wcawijngaards commented 3 years ago

It seems like NSD is emitting these three NSEC3 records, the closest encloser hash(ug)=8r4... and the qname denial the hash(ira.go.ug) is sks8feam03k55b2mg7jg22jiacq57pbs and the qk9... record denies it. The dpk... record denies the next-closer, it is hash(go.ug) is f8shj4rsfkis1fn5930m5otqn8dpv8i3. To create the proof, the closest encloser and next encloser records must be present to provide the closestencloser part of the proof. This is necessary because it must be signed with optout. It would also be needed for like unsigned-referrals. The go.ug is an empty nonterminal. These have been the cause of interop issues, with signers producing different nsec3 records, and other issues. So the response from NSD now, includes also the qname denial nsec3, that the others do not include. It would not be needed for a delegation, but since it is a nodata answer this is not a delegation. Perhaps we should fix it, but I also do not want other interop issues. Although if the other servers serve it maybe so can we.

wcawijngaards commented 3 years ago

After looking at it I think that NSD adds the third NSEC3 record because it is required. That is the record that has the optout bit that is pertinent for this span of domain names. So, this record proves if the destination is covered by an optout NSEC3 span or not. Now, NSD adds it without checking if optout is in use. In the given zone optout is enabled for the output you have.

So there is unique information in that NSEC3 that is not actually present in the other ones. The other NSEC3 records also have an optout flag, but this may apply to a different span of domain names.

I think this is the reason that the third NSEC3 record is present. It is a surprisingly good reason.

The other code works in practice, I presume, that you cite, thus it may be that the information is not used in any way.

wcawijngaards commented 3 years ago

Fixed this in the commit, it only includes the qname denial if there is no intermediate (empty nonterminal) with an NSEC3 record covering it. That makes it do 2 NSEC3s for such a NODATA answer. The issue is specifically for query type DS and empty nonterminals with optout NSEC3.