99 lines
3.4 KiB
Diff
99 lines
3.4 KiB
Diff
From 8ce27433f8b2e17c557cb55e4f16941d309deeac Mon Sep 17 00:00:00 2001
|
|
From: Simon Kelley <simon@thekelleys.org.uk>
|
|
Date: Fri, 17 Jan 2025 17:49:29 +0000
|
|
Subject: [PATCH] Handle DS queries to auth zones.
|
|
Origin: upstream, v2.91test8
|
|
|
|
When dnsmasq is configured to act as an authoritative server and has
|
|
an authoritative zone configured, and recieves a query for
|
|
that zone _as_forwarder_ it answers the query directly rather
|
|
than forwarding it. This doesn't affect the answer, but it
|
|
saves dnsmasq forwarding the query to the recusor upstream,
|
|
whch then bounces it back to dnsmasq in auth mode. The
|
|
exception should be when the query is for the root of zone, for a DS
|
|
RR. The answer to that has to come from the parent, via the
|
|
recursor, and will typically be a proof-of-nonexistence since
|
|
dnsmasq doesn't support signed zones. This patch suppresses
|
|
local answers and forces forwarding to the upstream recursor
|
|
for such queries. It stops breakage when a DNSSEC validating
|
|
client makes queries to dnsmasq acting as forwarder for a zone
|
|
for which it is authoritative.
|
|
|
|
[ukleinek: drop changes to CHANGELOG to prevent conflicts]
|
|
---
|
|
src/forward.c | 52 +++++++++++++++++++++++++++++++++++++--------------
|
|
1 file changed, 38 insertions(+), 14 deletions(-)
|
|
|
|
--- a/src/forward.c
|
|
+++ b/src/forward.c
|
|
@@ -1744,15 +1744,27 @@ void receive_query(struct listener *list
|
|
#endif
|
|
|
|
#ifdef HAVE_AUTH
|
|
- /* find queries for zones we're authoritative for, and answer them directly */
|
|
+ /* Find queries for zones we're authoritative for, and answer them directly.
|
|
+ The exception to this is DS queries for the zone route. They
|
|
+ have to come from the parent zone. Since dnsmasq's auth server
|
|
+ can't do DNSSEC, the zone will be unsigned, and anything using
|
|
+ dnsmasq as a forwarder and doing validation will be expecting to
|
|
+ see the proof of non-existence from the parent. */
|
|
if (!auth_dns && !option_bool(OPT_LOCALISE))
|
|
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
|
- if (in_zone(zone, daemon->namebuff, NULL))
|
|
- {
|
|
- auth_dns = 1;
|
|
- local_auth = 1;
|
|
- break;
|
|
- }
|
|
+ {
|
|
+ char *cut;
|
|
+
|
|
+ if (in_zone(zone, daemon->namebuff, &cut))
|
|
+ {
|
|
+ if (type != T_DS || cut)
|
|
+ {
|
|
+ auth_dns = 1;
|
|
+ local_auth = 1;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
#endif
|
|
|
|
#ifdef HAVE_LOOP
|
|
@@ -2268,15 +2280,27 @@ unsigned char *tcp_request(int confd, ti
|
|
&peer_addr, auth_dns ? "auth" : "query", qtype);
|
|
|
|
#ifdef HAVE_AUTH
|
|
- /* find queries for zones we're authoritative for, and answer them directly */
|
|
+ /* Find queries for zones we're authoritative for, and answer them directly.
|
|
+ The exception to this is DS queries for the zone route. They
|
|
+ have to come from the parent zone. Since dnsmasq's auth server
|
|
+ can't do DNSSEC, the zone will be unsigned, and anything using
|
|
+ dnsmasq as a forwarder and doing validation will be expecting to
|
|
+ see the proof of non-existence from the parent. */
|
|
if (!auth_dns && !option_bool(OPT_LOCALISE))
|
|
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
|
- if (in_zone(zone, daemon->namebuff, NULL))
|
|
- {
|
|
- auth_dns = 1;
|
|
- local_auth = 1;
|
|
- break;
|
|
- }
|
|
+ {
|
|
+ char *cut;
|
|
+
|
|
+ if (in_zone(zone, daemon->namebuff, &cut))
|
|
+ {
|
|
+ if (qtype != T_DS || cut)
|
|
+ {
|
|
+ auth_dns = 1;
|
|
+ local_auth = 1;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
#endif
|
|
}
|
|
}
|