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