dnsmasq: add fix related to DNSSEC verification from upstream
authorUwe Kleine-König <uwe+openwrt@kleine-koenig.org>
Mon, 27 Jan 2025 15:12:23 +0000 (16:12 +0100)
committerHauke Mehrtens <hauke@hauke-m.de>
Mon, 27 Jan 2025 22:38:02 +0000 (23:38 +0100)
To find the DS record for a given zone the parent zone's nameserver must
be queried and not the nameserver for the zone. Otherwise DNSSEC
verification for unsigned delegations breaks.

Signed-off-by: Uwe Kleine-König <uwe+openwrt@kleine-koenig.org>
Link: https://patchwork.ozlabs.org/project/openwrt/patch/20250127151223.1420006-1-uwe+openwrt@kleine-koenig.org/
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
package/network/services/dnsmasq/Makefile
package/network/services/dnsmasq/patches/0003-Handle-DS-queries-to-auth-zones.patch [new file with mode: 0644]

index 0a597c03ce405b078b67b8c4b52835b2d91f72b5..47a5ae54ae7f5ca2f3cdb0918f58d7517e579c6e 100644 (file)
@@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
 PKG_NAME:=dnsmasq
 PKG_UPSTREAM_VERSION:=2.90
 PKG_VERSION:=$(subst test,~~test,$(subst rc,~rc,$(PKG_UPSTREAM_VERSION)))
-PKG_RELEASE:=3
+PKG_RELEASE:=4
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_UPSTREAM_VERSION).tar.xz
 PKG_SOURCE_URL:=https://thekelleys.org.uk/dnsmasq/
diff --git a/package/network/services/dnsmasq/patches/0003-Handle-DS-queries-to-auth-zones.patch b/package/network/services/dnsmasq/patches/0003-Handle-DS-queries-to-auth-zones.patch
new file mode 100644 (file)
index 0000000..bd7270c
--- /dev/null
@@ -0,0 +1,98 @@
+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
+           }
+       }