Hey Simon,

this patch adds a method for deprecating ANY queries (following RFC 8482: Providing Minimal-Sized Responses to DNS Queries That Have QTYPE=ANY). This conforms to how many of the large scale upstream DNS providers (Google, Cloudflare to name only a few) are dealing with the use_less_ness of ANY in general on one hand but the unfortunate use_full_ness in DNS amplification attacks on the other hand. Another solution could be only disallowing ANY queries over UDP and forcing clients to re-try over TCP but - given how useless ANY is - it doesn't seem worth implementing this more complex path.

The proposed option --no-ANY simply ensures dnsmasq will not add any RRs for such questions.

We are looking forward to enable it by default in Pi-hole v6.0+ given this patch is accepted.

Best,
Dominik
From ac3134c48ef3ee6ec9be2f3b0993f710ac36f8f8 Mon Sep 17 00:00:00 2001
From: DL6ER <dl...@dl6er.de>
Date: Tue, 6 Feb 2024 17:51:22 +0100
Subject: [PATCH] Add option --no-ANY providing minimal-sized responses to ANY
 queries (RFC 8482)

Signed-off-by: DL6ER <dl...@dl6er.de>
---
 CHANGELOG     | 4 ++++
 man/dnsmasq.8 | 9 +++++++++
 src/dnsmasq.h | 3 ++-
 src/option.c  | 3 +++
 src/rfc1035.c | 8 ++++++++
 5 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG b/CHANGELOG
index 2ce53a8..75575b5 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -25,6 +25,10 @@ version 2.90
 	end up in the query also. This bug only seems to cause problems
 	when the usptream server is a DOH/DOT proxy. Thanks to Justin He
 	for the bug report.
+
+	Add --no-ANY option to stop processing ANY queries.
+	The ANY type has been deprecated by RFC 8482, and is a common vector
+	for DNS amplification attacks.
 	
 	
 version 2.89
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index bb8da54..1a7a280 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -388,6 +388,15 @@ Remove AAAA records from answers. No IPv6 addresses will be returned.
 .B --filter-rr=<rrtype>[,<rrtype>...]
 Remove records of the specified type(s) from answers.
 .TP
+.B --no-ANY
+Provide minimal-sized responses to ANY DNS queries instead of processing them.
+Queries with QTYPE=ANY are frequently observed as part of reflection attacks,
+since a relatively small query can be used to elicit a large response. This is a desirable
+characteristic if the goal is to maximize the amplification potential of a DNS server as
+part of a volumetric attack. With this option being enabled, minimal responses are returned making
+dnsmasq a much less useful amplifier.
+The follows RFC 8482 which effectively deprecates the DNS ANY query type.
+.TP
 .B --cache-rr=<rrtype>[,<rrtype>...]
 By default, dnsmasq caches A, AAAA, CNAME and SRV DNS record types.
 This option adds other record types to the cache. The RR-type can be given
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 129e2c9..9ec4d39 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -282,7 +282,8 @@ struct event_desc {
 #define OPT_NO_IDENT       70
 #define OPT_CACHE_RR       71
 #define OPT_LOCALHOST_SERVICE  72
-#define OPT_LAST           73
+#define OPT_NO_ANY         73
+#define OPT_LAST           74
 
 #define OPTION_BITS (sizeof(unsigned int)*8)
 #define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
diff --git a/src/option.c b/src/option.c
index 0cb691e..a5297eb 100644
--- a/src/option.c
+++ b/src/option.c
@@ -191,6 +191,7 @@ struct myoption {
 #define LOPT_NO_DHCP6      382
 #define LOPT_NO_DHCP4      383
 #define LOPT_MAX_PROCS     384
+#define LOPT_NO_ANY        385
 
 #ifdef HAVE_GETOPT_LONG
 static const struct option opts[] =  
@@ -231,6 +232,7 @@ static const struct myoption opts[] =
     { "filter-A", 0, 0, LOPT_FILTER_A },
     { "filter-AAAA", 0, 0, LOPT_FILTER_AAAA },
     { "filter-rr", 1, 0, LOPT_FILTER_RR },
+    { "no-ANY", 0, 0, LOPT_NO_ANY },
     { "pid-file", 2, 0, 'x' },
     { "strict-order", 0, 0, 'o' },
     { "server", 1, 0, 'S' },
@@ -416,6 +418,7 @@ static struct {
   { LOPT_FILTER_A, ARG_DUP, NULL, gettext_noop("Don't include IPv4 addresses in DNS answers."), NULL },
   { LOPT_FILTER_AAAA, ARG_DUP, NULL, gettext_noop("Don't include IPv6 addresses in DNS answers."), NULL },
   { LOPT_FILTER_RR, ARG_DUP, "<RR-type>", gettext_noop("Don't include resource records of the given type in DNS answers."), NULL },
+  { LOPT_NO_ANY, OPT_NO_ANY, NULL, gettext_noop("Don't reply to ANY requests"), NULL },
   { 'F', ARG_DUP, "<ipaddr>,...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
   { 'g', ARG_ONE, "<groupname>", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
   { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 04b1472..423a4b4 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1550,6 +1550,14 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
 
       ans = 0; /* have we answered this question */
 
+      /* Do not answer ANY queries if requested */
+      if (qtype == T_ANY && option_bool(OPT_NO_ANY))
+	{
+	  sec_data = 0;
+	  log_query(F_CONFIG | F_NEG, name, &addr, NULL, 0);
+	  continue; /* Skip to next question */
+	}
+
       if (qclass == C_IN)
 	while (--count != 0 && (crecp = cache_find_by_name(NULL, name, now, F_CNAME | F_NXDOMAIN)))
 	  {
-- 
2.34.1

_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss

Reply via email to