Bug 782 - NSD does not correctly deliver DS records for delegated zones on the same authoritative NS
NSD does not correctly deliver DS records for delegated zones on the same aut...
Product: NSD
Classification: Unclassified
Component: NSD Code
x86_64 Linux
: P5 normal
Assigned To: NSD team
Depends on:
  Show dependency treegraph
Reported: 2016-06-22 12:51 CEST by Tobias Fiebig
Modified: 2016-07-04 20:00 CEST (History)
2 users (show)

See Also:


Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Fiebig 2016-06-22 12:51:08 CEST
I experienced the following issue with nsd:

We have two dnssec signed zones, parent and child, on a powerdns hidden master
that pushes these to two nsd frontends. we have a parent zone zone.tld and a
child test.zone.tld. Both are supposed to be served by the same NS, there is no
lazy delegation.

Paraphrased zone setting:

===== parent zone.tld
zone.tld IN NS ans1.zone.tld
zone.tld IN NS ans2.zone.tld

; no lazy delegation
test.zone.tld IN NS ans1.zone.tld
test.zone.tld IN NS ans2.zone.tld

; DNSKEY for this zone
zone.tld IN DNSKEY ...

; DS for the child zone
test.zone.tld IN DS ...

bar.zone.tld IN A

===== child test.zone.tld

test.zone.tld IN NS ans1.zone.tld
test.zone.tld IN NS ans2.zone.tld

; DNSKEY for this zone
test.zone.tld IN DNSKEY ...

foo.test.zone.tld IN A


Both zones are propagated to the NSD frontends (normal master/slave delegation).
SOAs are up to date for a dig SOA @ans1/ans2 (test.)zone.tld. Both ans 
however do not return a DS for test.zone.tld, but instead an NXdomain.

The following debug actions have already been taken:

1. Deconfigure test.zone.tld on ans1/ans2. The DS for test.zone.tld is then
correctly delivered uppon request. 

2. With test.zone.tld and zone.tld configured on both NS, add a DS entry to
test.zone.tld. This does not change the beheaviour of nsd, and no DS is delivered.

3. perform AXFR requests from the ANS to the hidden master. All required records
were found in the responses

4. validate that the on-disk zone-files do contain the correct records.

Sadly, the corresponding setup was thereafter migrated to powerdns, which provides
the desired beheaviour. However, if necessary, i can quickly replicate this
scenario in a test case.
Comment 1 Ralph Dolmans 2016-06-24 17:32:16 CEST
Hi Tobias,

Thanks for your detailed bug report. The described behaviour is, obviously, not correct.

I tried to reproduce your set-up, but do not get the described problems. I am able to query the DS and my resolver is capable of validating the answers.

Is it correct that you do get answers from the child zone for different RRTYPEs? Are you using the trunk version of NSD? It would be of great help if you can provide a test set-up.

-- Ralph
Comment 2 Tobias Fiebig 2016-06-24 20:48:31 CEST
Yes, different RRTYPES worked fine. I am using the version that is in EL6, not sure if  it comes from EPEL or base atm though (not at work). Will set up a demosystem on monday.
Comment 3 Tobias Fiebig 2016-07-04 15:28:51 CEST
I have now reproduced the issue on another infrastructure.

You can hit test.fgsect.de / fgsect.de on ans0.sec.t-labs.tu-berlin.de and ans1.sec.t-labs.tu-berlin.de . 

A dig for the DS of that zone successfully returns the NSEC (using NSEC for the test domain only) NXdomain from the child zone.

Removing the child from the nsd.conf and restarting nsd again leads to the DS being correctly returned. 

We run 4.1.7-3.el6 from epel.
Comment 4 Wouter Wijngaards 2016-07-04 15:48:45 CEST
Hi Tobias,

I think the parent zone may not have the NS rrset for test.fgsect.de loaded.  This is what NSD uses to find out where to get the DS record from.  This is wrong, and you should have the NS record.

Is that what the problem was?  Here is a codefix for that issue:
(also put it in the code repository):

Index: namedb.c
--- namedb.c	(revision 4652)
+++ namedb.c	(working copy)
@@ -533,7 +533,7 @@
 zone_type *
-domain_find_parent_zone(zone_type* zone)
+domain_find_parent_zone(namedb_type* db, zone_type* zone)
 	rrset_type* rrset;
@@ -544,6 +544,10 @@
 			return rrset->zone;
+	/* the NS record in the parent zone above this zone is not present,
+	 * workaround to find that parent zone anyway */
+	if(zone->apex->parent)
+		return domain_find_zone(db, zone->apex->parent);
 	return NULL;
Index: namedb.h
--- namedb.h	(revision 4652)
+++ namedb.h	(working copy)
@@ -232,7 +232,7 @@
 rrset_type* domain_find_any_rrset(domain_type* domain, zone_type* zone);
 zone_type* domain_find_zone(namedb_type* db, domain_type* domain);
-zone_type* domain_find_parent_zone(zone_type* zone);
+zone_type* domain_find_parent_zone(namedb_type* db, zone_type* zone);
 domain_type* domain_find_ns_rrsets(domain_type* domain, zone_type* zone, rrset_type **ns);
 /* find DNAME rrset in domain->parent or higher and return that domain */
Index: query.c
--- query.c	(revision 4652)
+++ query.c	(working copy)
@@ -1210,7 +1210,7 @@
 		 * parent zone to generate the answer if we are
 		 * authoritative for the parent zone.
-		zone_type *zone = domain_find_parent_zone(q->zone);
+		zone_type *zone = domain_find_parent_zone(nsd->db, q->zone);
 		if (zone)
 			q->zone = zone;
Comment 5 Tobias Fiebig 2016-07-04 20:00:13 CEST
apparently overlooked the parent NS entries in the reproduction-case. Still, i am rather certain, that delegation was done correctly in the initial case. However... for the case at hand fixing the delegation fixes the issue. Hence, i assume pebkac on my end.

Concerning the code changes... I am personally not sure, if that is the right way to go... however, that is not my department. From my point of view this ticket can be closed, sorry for bothering you.