[Dnsmasq-discuss] DNSSEC validation fails when signed DNAME record is involved -- failing to validate DNAME's synthesized CNAME?
Simon Kelley
simon at thekelleys.org.uk
Fri Mar 14 12:52:51 UTC 2025
Graham, thanks for this comprehensive exposition of the problem.
You are entirely correct that this particular bit of the DNS Camel has
passe me by up to this point.
The behavior mandated by RFC4035 looks pretty straightforward to
implement, and would, I think solve your immediate problem. The stuff in
RFC 6672 will need quite a lot more head-scratching.
In any case, I'll address both of these, but not for the long-delayed
2.91 release; that just needs to be out there now for all the things it
does fix.
Cheers,
Simon.
On 3/12/25 12:05, Clinch, Graham wrote:
> Hello,
>
> We have a pair of signed DNS zones: lancs.ac.uk & lancaster.ac.uk.
> lancaster.ac.uk contains a DNAME record which "redirects" all names
> beneath it to the same name within lancs.ac.uk (i.e.
> abc.def.lancaster.ac.uk becomes abc.def.lancs.ac.uk).
>
> -=-
>
> $ dig www.lancaster.ac.uk
>
> […]
>
> ;; ANSWER SECTION:
>
> lancaster.ac.uk. 43200 IN DNAME
> lancs.ac.uk.
>
> www.lancaster.ac.uk. 43200 IN CNAME
> www.lancs.ac.uk.
>
> www.lancs.ac.uk. 3600 IN A 148.88.65.80
>
> -=-
>
> Bind, unbound & knot resolver are happy to (validate &) resolve names
> beneath either zone (although kresd had difficulty before 2020: https://
> gitlab.nic.cz/knot/knot-resolver/-/issues/234 <https://gitlab.nic.cz/
> knot/knot-resolver/-/issues/234>), and dnsviz reports no errors (eg
> https://dnsviz.net/d/www.lancaster.ac.uk/dnssec/ <https://dnsviz.net/d/
> www.lancaster.ac.uk/dnssec/>) so we believe the zones are configured
> reasonably.
>
> dnsmasq, when dnssec validation is enabled, is unhappy with names
> beneath lancaster.ac.uk. I suspect that dnsmasq is unsure how to
> validate the synthesized, unsigned (correctly: rfc 4035 sect. 3 final
> para), CNAME record - a quick skim of dnsmasq's source doesn't show as
> much referencing of T_DNAME as I would expect for a DNAME-aware resolver).
>
> I've recreated this with dnsmasq 2.91rc5:
>
> -=-
>
> # make COPTS=-DHAVE_DNSSEC
>
> […]
>
> # ./src/dnsmasq --version
>
> Dnsmasq version 2.91rc5 Copyright (c) 2000-2025 Simon Kelley
>
> Compile time options: IPv6 GNU-getopt no-DBus no-UBus no-i18n no-IDN
> DHCP DHCPv6 no-Lua TFTP no-conntrack ipset no-nftset auth DNSSEC loop-
> detect inotify dumpfile
>
> This software comes with ABSOLUTELY NO WARRANTY.
>
> Dnsmasq is free software, and you are welcome to redistribute it
>
> under the terms of the GNU General Public License, version 2 or 3.
>
> -=-
>
> ===
>
> First, without dnssec validation, resolution is successful:
>
> -=-
>
> $ dig -p 5353 @127.0.0.1 www.lancaster.ac.uk
>
> ; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> -p 5353 @127.0.0.1
> www.lancaster.ac.uk
>
> ; (1 server found)
>
> ;; global options: +cmd
>
> ;; Got answer:
>
> ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19572
>
> ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
>
> ;; OPT PSEUDOSECTION:
>
> ; EDNS: version: 0, flags:; udp: 1232
>
> ; COOKIE: b6f0093fa57419c20100000067d16e0a0b00303eb49db846 (good)
>
> ;; QUESTION SECTION:
>
> ;www.lancaster.ac.uk. IN A
>
> ;; ANSWER SECTION:
>
> lancaster.ac.uk. 43200 IN DNAME
> lancs.ac.uk.
>
> www.lancaster.ac.uk. 43200 IN CNAME
> wWw.lancs.ac.uk.
>
> www.lancs.ac.uk. 3600 IN A 148.88.65.80
>
> ;; Query time: 0 msec
>
> ;; SERVER: 127.0.0.1#5353(127.0.0.1) (UDP)
>
> ;; WHEN: Wed Mar 12 11:20:42 GMT 2025
>
> ;; MSG SIZE rcvd: 154
>
> -=-
>
> -=-
>
> # ./src/dnsmasq --listen-address=127.0.0.1 --no-daemon --no-hosts --
> port=5353 --log-queries --no-resolv --server=148.88.65.52
>
> dnsmasq: started, version 2.91rc5 cachesize 150
>
> dnsmasq: compile time options: IPv6 GNU-getopt no-DBus no-UBus no-i18n
> no-IDN DHCP DHCPv6 no-Lua TFTP no-conntrack ipset no-nftset auth DNSSEC
> loop-detect inotify dumpfile
>
> dnsmasq: using nameserver 148.88.65.52#53
>
> dnsmasq: cleared cache
>
> dnsmasq: query[A] www.lancaster.ac.uk from 127.0.0.1
>
> dnsmasq: forwarded www.lancaster.ac.uk to 148.88.65.52
>
> dnsmasq: reply www.lancaster.ac.uk is <CNAME>
>
> dnsmasq: reply www.lancs.ac.uk is 148.88.65.80
>
> -=-
>
> ===
>
> Then, with dnssec validation enabled, the status is SERVFAIL, with an
> "NSEC Missing" error:
>
> -=-
>
> $ dig -p 5353 @127.0.0.1 www.lancaster.ac.uk
>
> ; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> -p 5353 @127.0.0.1
> www.lancaster.ac.uk
>
> ; (1 server found)
>
> ;; global options: +cmd
>
> ;; Got answer:
>
> ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 18645
>
> ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
>
> ;; OPT PSEUDOSECTION:
>
> ; EDNS: version: 0, flags:; udp: 1232
>
> ; COOKIE: efab28c4571261b60100000067d16e90e4d4929c967d9830 (good)
>
> ; EDE: 12 (NSEC Missing)
>
> ;; QUESTION SECTION:
>
> ;www.lancaster.ac.uk. IN A
>
> ;; Query time: 32 msec
>
> ;; SERVER: 127.0.0.1#5353(127.0.0.1) (UDP)
>
> ;; WHEN: Wed Mar 12 11:22:56 GMT 2025
>
> ;; MSG SIZE rcvd: 82
>
> -=-
>
> -=-
>
> # ./src/dnsmasq --listen-address=127.0.0.1 --no-daemon --no-hosts --
> port=5353 --log-queries --no-resolv --server=148.88.65.52 --dnssec
>
> dnsmasq: started, version 2.91rc5 cachesize 150
>
> dnsmasq: compile time options: IPv6 GNU-getopt no-DBus no-UBus no-i18n
> no-IDN DHCP DHCPv6 no-Lua TFTP no-conntrack ipset no-nftset auth DNSSEC
> loop-detect inotify dumpfile
>
> dnsmasq: DNSSEC validation enabled
>
> dnsmasq: configured with trust anchor for <root> keytag 20326
>
> dnsmasq: using nameserver 148.88.65.52#53
>
> dnsmasq: cleared cache
>
> dnsmasq: query[A] www.lancaster.ac.uk from 127.0.0.1
>
> dnsmasq: forwarded www.lancaster.ac.uk to 148.88.65.52
>
> dnsmasq: dnssec-query[DS] uk to 148.88.65.52
>
> dnsmasq: dnssec-query[DNSKEY] . to 148.88.65.52
>
> dnsmasq: reply . is DNSKEY keytag 20326, algo 8
>
> dnsmasq: reply . is DNSKEY keytag 38696, algo 8
>
> dnsmasq: reply . is DNSKEY keytag 26470, algo 8
>
> dnsmasq: reply uk is DS for keytag 43876, algo 8, digest 2
>
> dnsmasq: dnssec-query[DS] ac.uk to 148.88.65.52
>
> dnsmasq: dnssec-query[DNSKEY] uk to 148.88.65.52
>
> dnsmasq: reply uk is DNSKEY keytag 43876, algo 8
>
> dnsmasq: reply uk is DNSKEY keytag 43056, algo 8
>
> dnsmasq: reply ac.uk is DS for keytag 45874, algo 8, digest 2
>
> dnsmasq: dnssec-query[DS] lancaster.ac.uk to 148.88.65.52
>
> dnsmasq: dnssec-query[DNSKEY] ac.uk to 148.88.65.52
>
> dnsmasq: reply ac.uk is truncated
>
> dnsmasq: dnssec-query[DNSKEY] ac.uk to 148.88.65.52
>
> dnsmasq: reply ac.uk is DNSKEY keytag 63831, algo 8
>
> dnsmasq: reply ac.uk is DNSKEY keytag 63490, algo 8
>
> dnsmasq: reply ac.uk is DNSKEY keytag 54274, algo 8
>
> dnsmasq: reply ac.uk is DNSKEY keytag 45874, algo 8
>
> dnsmasq: reply lancaster.ac.uk is DS for keytag 18943, algo 13, digest 2
>
> dnsmasq: dnssec-query[DNSKEY] lancaster.ac.uk to 148.88.65.52
>
> dnsmasq: reply lancaster.ac.uk is DNSKEY keytag 52067, algo 13
>
> dnsmasq: reply lancaster.ac.uk is DNSKEY keytag 18943, algo 13
>
> dnsmasq: dnssec-query[DS] www.lancaster.ac.uk to 148.88.65.52
>
> dnsmasq: dnssec-query[DS] lancs.ac.uk to 148.88.65.52
>
> dnsmasq: reply lancs.ac.uk is DS for keytag 30106, algo 13, digest 2
>
> dnsmasq: dnssec-query[DNSKEY] lancs.ac.uk to 148.88.65.52
>
> dnsmasq: reply lancs.ac.uk is DNSKEY keytag 30106, algo 13
>
> dnsmasq: reply lancs.ac.uk is DNSKEY keytag 37821, algo 13
>
> dnsmasq: validation www.lancaster.ac.uk is BOGUS
>
> -=-
>
> ===
>
> As an aside, see that a request for the lancaster.ac.uk DNAME itself is
> indeed successful:
>
> -=-
>
> $ dig -p 5353 @127.0.0.1 DNAME lancaster.ac.uk
>
> ; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> -p 5353 @127.0.0.1 DNAME
> lancaster.ac.uk
>
> ; (1 server found)
>
> ;; global options: +cmd
>
> ;; Got answer:
>
> ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55357
>
> ;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
>
> ;; OPT PSEUDOSECTION:
>
> ; EDNS: version: 0, flags:; udp: 1232
>
> ; COOKIE: d05676a64991eea80100000067d16ece6573dd2d0a5376b5 (good)
>
> ;; QUESTION SECTION:
>
> ;lancaster.ac.uk. IN DNAME
>
> ;; ANSWER SECTION:
>
> lancaster.ac.uk. 43200 IN DNAME
> lancs.ac.uk.
>
> ;; Query time: 40 msec
>
> ;; SERVER: 127.0.0.1#5353(127.0.0.1) (UDP)
>
> ;; WHEN: Wed Mar 12 11:23:58 GMT 2025
>
> ;; MSG SIZE rcvd: 112
>
> -=-
>
> -=-
>
> # ./src/dnsmasq --listen-address=127.0.0.1 --no-daemon --no-hosts --
> port=5353 --log-queries --no-resolv --server=148.88.65.52 --dnssec
>
> dnsmasq: started, version 2.91rc5 cachesize 150
>
> dnsmasq: compile time options: IPv6 GNU-getopt no-DBus no-UBus no-i18n
> no-IDN DHCP DHCPv6 no-Lua TFTP no-conntrack ipset no-nftset auth DNSSEC
> loop-detect inotify dumpfile
>
> dnsmasq: DNSSEC validation enabled
>
> dnsmasq: configured with trust anchor for <root> keytag 20326
>
> dnsmasq: using nameserver 148.88.65.52#53
>
> dnsmasq: cleared cache
>
> dnsmasq: query[DNAME] lancaster.ac.uk from 127.0.0.1
>
> dnsmasq: forwarded lancaster.ac.uk to 148.88.65.52
>
> dnsmasq: dnssec-query[DS] uk to 148.88.65.52
>
> dnsmasq: dnssec-query[DNSKEY] . to 148.88.65.52
>
> dnsmasq: reply . is DNSKEY keytag 26470, algo 8
>
> dnsmasq: reply . is DNSKEY keytag 20326, algo 8
>
> dnsmasq: reply . is DNSKEY keytag 38696, algo 8
>
> dnsmasq: reply uk is DS for keytag 43876, algo 8, digest 2
>
> dnsmasq: dnssec-query[DS] ac.uk to 148.88.65.52
>
> dnsmasq: dnssec-query[DNSKEY] uk to 148.88.65.52
>
> dnsmasq: reply uk is DNSKEY keytag 43056, algo 8
>
> dnsmasq: reply uk is DNSKEY keytag 43876, algo 8
>
> dnsmasq: reply ac.uk is DS for keytag 45874, algo 8, digest 2
>
> dnsmasq: dnssec-query[DS] lancaster.ac.uk to 148.88.65.52
>
> dnsmasq: dnssec-query[DNSKEY] ac.uk to 148.88.65.52
>
> dnsmasq: reply ac.uk is truncated
>
> dnsmasq: dnssec-query[DNSKEY] ac.uk to 148.88.65.52
>
> dnsmasq: reply ac.uk is DNSKEY keytag 45874, algo 8
>
> dnsmasq: reply ac.uk is DNSKEY keytag 54274, algo 8
>
> dnsmasq: reply ac.uk is DNSKEY keytag 63831, algo 8
>
> dnsmasq: reply ac.uk is DNSKEY keytag 63490, algo 8
>
> dnsmasq: reply lancaster.ac.uk is DS for keytag 18943, algo 13, digest 2
>
> dnsmasq: dnssec-query[DNSKEY] lancaster.ac.uk to 148.88.65.52
>
> dnsmasq: reply lancaster.ac.uk is DNSKEY keytag 52067, algo 13
>
> dnsmasq: reply lancaster.ac.uk is DNSKEY keytag 18943, algo 13
>
> dnsmasq: validation result is SECURE
>
> dnsmasq: reply lancaster.ac.uk is <DNAME>
>
> -=-
>
> ===
>
> For reference, here is the result of querying unbound with validation
> enabled:
>
> -=-
>
> $ dig +short @127.0.0.1 txt ch version.bind
>
> "unbound 1.17.1"
>
> $ dig @127.0.0.1 www.lancaster.ac.uk
>
> ; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> @127.0.0.1 www.lancaster.ac.uk
>
> ; (1 server found)
>
> ;; global options: +cmd
>
> ;; Got answer:
>
> ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31627
>
> ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
>
> ;; OPT PSEUDOSECTION:
>
> ; EDNS: version: 0, flags:; udp: 1232
>
> ;; QUESTION SECTION:
>
> ;www.lancaster.ac.uk. IN A
>
> ;; ANSWER SECTION:
>
> lancaster.ac.uk. 43200 IN DNAME
> lancs.ac.uk.
>
> www.lancaster.ac.uk. 43200 IN CNAME
> www.lancs.ac.uk.
>
> www.lancs.ac.uk. 3600 IN A 148.88.65.80
>
> ;; Query time: 72 msec
>
> ;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
>
> ;; WHEN: Wed Mar 12 11:30:09 GMT 2025
>
> ;; MSG SIZE rcvd: 113
>
> -=-
>
> RFC 4035 section 4.8 and RFC 6672 section 5.3 describe some of the
> contortions required to validate when a DNAME is involved.
>
> DNSSEC signing is rare, and DNAME records are also rare, so I am
> unfortunately not aware of any other real-world instances of signed
> DNAMEs. Other (unsigned) DNAME records seen in the wild include oxford-
> brookes.ac.uk & hrz.uni-bonn.de.
>
> With thanks,
>
> Graham
>
>
> _______________________________________________
> Dnsmasq-discuss mailing list
> Dnsmasq-discuss at lists.thekelleys.org.uk
> https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss
More information about the Dnsmasq-discuss
mailing list