No RRSIG for

When I visit with DNSSEC enabled on my resolver, it says I’m not using It works perfectly on any website, and I’m clearly using, however my resolver notes that there’s no RRSIG for the CNAME at

Since is signed it denies the request as BOGUS. Is this as designed, or is it a bug in the implementation?

I had a search around and I can’t see anyone else querying this. Of course it’s not a big issue, but it still seems like an oversight.


Can you post your debug URL of

1 Like

Hi! is a signed zone, but isn’t, so there’s no RRSIG for the CNAME inside.

Does that mean there’s a bug in the DNSSEC implementation in dnsmasq? I’m not sure how it can determine an unsigned subdomain?

Is there a correct implementation of NSEC on this domain?

Hmmm. Using this tool:

It appears that the NSEC record for is returned by and but not perhaps the issue is actually with the Cloudflare DNS itself?

What NSEC record are you looking for? These are the nameservers for the parent zone:

% kdig NS +dnssec
...      	86400	IN	NS      	86400	IN	NS      	86400	IN	RRSIG	NS 13 2 86400 20220413181203 20220411161203 34505 AAhHH40GOyE/LG1MuoN4TsNBS3dHk1UmUV6/EDmmFOD1W5zj2rATTT3qMgmVUByhzaysXZSjzP6V5AtOt0srCQ==

You can query them for a DS record to confirm that it doesn’t exist:

% kdig DS +dnssec
...      	3600	IN	SOA 2274099322 10000 2400 604800 3600 	3600	IN	NSEC	help\ NS RRSIG NSEC 	3600	IN	RRSIG	NSEC 13 3 3600 20220413181246 20220411161246 34505 4EqR55iKEydISi0B5c89BuvlLBKqNZFhAwRcXMPn9NU67djx2HHT/2gpv4gEJ5Ou0l/mfflkTE7O3qDq3DuOPw==      	3600	IN	RRSIG	SOA 13 2 3600 20220413181246 20220411161246 34505 uIO9VXckHbcRcTLryuJ5ZTzz4U0elgqOLk34+PeW/b8fEXgYIRIfas6mTfSwBKAH1O3WAArMqsqNQ5auvqnRgg==

The NSEC record here tells you that the name exists in the zone, but only has types NS RRSIG and NSEC, not DS.

When a delegation doesn’t have a signature, the zone underneath is not signed.

Here’s the summary: fails due to no RRSIG fails due to no resolves as a CNAME but INSECURE resolves as NXDOMAIN INSECURE

This is all with dnsmasq through a DNS-over-TLS proxy, hence expecting the is-dot one to resolve and the NXDOMAIN for the is-doh is expected.

Not sure why the is fine, but the is not??

I wonder if the answer lies in this comment from the dnsmasq source:

1799           F_NEG && !F_DNSSECOK implies that we've proved there's no DS record here,
1800           but that's because there's no NS record either, ie this isn't the start
1801           of a zone. We only prove that the DNS tree below a node is unsigned when
1802           we prove that we're at a zone cut AND there's no DS record. ```

More investigation required I think...

It seems to me that dnsmasq doesn’t find the correct authority for these records, and thinks it’s This is generally tricky for recursives/revalidators.

Ah ha! I’ve found the problem. Turns out that dnsmasq has a logic issue in that when it tries to validate the it tries to look up the DS for and correctly identifies it as being its own zone. However it then does the CNAME lookup for and gets confused and tries to look up its DS record, even though it’s already been returned its RRSIG.

I’m not entirely sure of the solution yet, but it seems that all the Cloudflare services are doing their thing just right.

For those interested, here’s the fix for dnsmasq:

diff --git a/src/dnssec.c b/src/dnssec.c
index 9965eea..8339a56 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -2001,8 +2001,15 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
 		  if (check_unsigned && i < ntohs(header->ancount))
 		      rc = zone_status(name, class1, keyname, now);
-		      if (STAT_ISEQUAL(rc, STAT_SECURE))
+		      {
+		        /* This is BOGUS, unless it's a CNAME because that can be in
+		           another zone and is validated separately */
+		        if (type1 == T_CNAME)
+		          rc = STAT_INSECURE;
+		        else
+		          rc = STAT_BOGUS | DNSSEC_FAIL_NOSIG;
+		      }
 		      if (class)
 			*class = class1; /* Class for NEED_DS or NEED_KEY */
1 Like

Turns out my previous patch was actually incorrect. Having re-visited the problem this evening and re-validated my assumptions, what was actually happening was the SECURE response was making it think that the INSECURE was actually spoofing. I’ve modified my previous patch to detect and allow this case.

diff --git a/src/dnssec.c b/src/dnssec.c
index 9965eea..ceb6250 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -2004,6 +2004,9 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
 		      if (STAT_ISEQUAL(rc, STAT_SECURE))
+		      if (STAT_ISEQUAL(rc, STAT_INSECURE) && type1 == T_CNAME)
+		        check_unsigned = 0;
 		      if (class)
 			*class = class1; /* Class for NEED_DS or NEED_KEY */
1 Like

So it turns out my initial assessment of this problem was incorrect…

The issue is actually that the Cloudflare DNS server replies to the query for with the following response: 0 IN CNAME 300 IN A 300 IN A

Note that there are no RRSIG responses in the above. However, if you query for then the following is returned:

||300|IN|RRSIG|A 13 3 300 20220422230710 20220420210710 34505 8+U9GXJEj2e65zKcf/oO2PiX98Jxn/c76zHd4qFZWug00gYJ8aqTNJb0 Ctl7ebVOQ6X4EfW3x9lPCfLbDJTB4w==|

Note the addition of the RRSIG in the response. This is what is causing the issues.


Thanks! Let me try to figure out what’s wrong with that.

1 Like

There should be an RRSIG on the A records now, looks like the DO bit wasn’t set on some of these generated test records.

Yup, working now! Thanks.

1 Like

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.