DNSSEC validation change for reverse lookups in RFC-1918 ranges and friends.

The large public DNS services seem not to return proof-of-nonexistence
for DS records at the start of RFC-1918 in-addr.arpa domains and the their
IPv6 equivalents. 10.in-addr.arpa, 168.192.in-addr.arpa etc.

Since dnsmasq already has an option which instructs it not bother
upstream servers with pointless queries about these address ranges,
namely --bogus-priv, we extend that to enable behaviour which allows
dnsmasq to assume that insecure NXDOMAIN replies for these domains
are expected and to assume that the domains are legitimately unsigned.

This behaviour only matters when some address range is directed to
another upstream server using --rev-server. In that case it allows
replies from that server to pass DNSSEC validation. Without such a
server configured, queries are never sent upstream so they are never
validated and the new behaviour is moot.
This commit is contained in:
Simon Kelley
2025-05-09 21:46:50 +01:00
parent 98189ff988
commit 8ddabd11bc
4 changed files with 16 additions and 2 deletions

View File

@@ -346,6 +346,10 @@ Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192
which are not found in /etc/hosts or the DHCP leases file are answered which are not found in /etc/hosts or the DHCP leases file are answered
with "no such domain" rather than being forwarded upstream. The with "no such domain" rather than being forwarded upstream. The
set of prefixes affected is the list given in RFC6303, for IPv4 and IPv6. set of prefixes affected is the list given in RFC6303, for IPv4 and IPv6.
Enabling this also subtly alters DNSSEC validation for reverse lookups in the
private ranges such that a non-secure DS record is accepted as proof that
the range is not signed. This works around behaviour by the public DNS services
which seem not to return validated proof-of-non-existence for DS records in these domains.
.TP .TP
.B \-V, --alias=[<old-ip>]|[<start-ip>-<end-ip>],<new-ip>[,<mask>] .B \-V, --alias=[<old-ip>]|[<start-ip>-<end-ip>],<new-ip>[,<mask>]
Modify IPv4 addresses returned from upstream nameservers; old-ip is Modify IPv4 addresses returned from upstream nameservers; old-ip is

View File

@@ -1430,6 +1430,7 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp,
int *offset, unsigned short type, unsigned short class, char *format, ...); int *offset, unsigned short type, unsigned short class, char *format, ...);
int in_arpa_name_2_addr(char *namein, union all_addr *addrp); int in_arpa_name_2_addr(char *namein, union all_addr *addrp);
int private_net(struct in_addr addr, int ban_localhost); int private_net(struct in_addr addr, int ban_localhost);
int private_net6(struct in6_addr *a, int ban_localhost);
/* extract_name ops */ /* extract_name ops */
#define EXTR_NAME_EXTRACT 1 #define EXTR_NAME_EXTRACT 1
#define EXTR_NAME_COMPARE 2 #define EXTR_NAME_COMPARE 2

View File

@@ -1020,7 +1020,16 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
{ {
if (STAT_ISEQUAL(rc, STAT_INSECURE)) if (STAT_ISEQUAL(rc, STAT_INSECURE))
{ {
if (lookup_domain(name, F_DOMAINSRV, NULL, NULL)) if (option_bool(OPT_BOGUSPRIV) &&
(flags = in_arpa_name_2_addr(name, &a)) &&
((flags == F_IPV6 && private_net6(&a.addr6, 0)) || (flags == F_IPV4 && private_net(a.addr4, 0))))
{
my_syslog(LOG_INFO, _("Insecure reply received for DS %s, assuming that's OK for a RFC-1918 address."), name);
neganswer = 1;
nons = 0; /* If we're faking a DS, fake one with an NS. */
neg_ttl = DNSSEC_ASSUMED_DS_TTL;
}
else if (lookup_domain(name, F_DOMAINSRV, NULL, NULL))
{ {
my_syslog(LOG_INFO, _("Insecure reply received for DS %s, assuming non-DNSSEC domain-specific server."), name); my_syslog(LOG_INFO, _("Insecure reply received for DS %s, assuming non-DNSSEC domain-specific server."), name);
neganswer = 1; neganswer = 1;

View File

@@ -424,7 +424,7 @@ int private_net(struct in_addr addr, int ban_localhost)
((ip_addr & 0xFFFFFFFF) == 0xFFFFFFFF) /* 255.255.255.255/32 (broadcast)*/ ; ((ip_addr & 0xFFFFFFFF) == 0xFFFFFFFF) /* 255.255.255.255/32 (broadcast)*/ ;
} }
static int private_net6(struct in6_addr *a, int ban_localhost) int private_net6(struct in6_addr *a, int ban_localhost)
{ {
/* Block IPv4-mapped IPv6 addresses in private IPv4 address space */ /* Block IPv4-mapped IPv6 addresses in private IPv4 address space */
if (IN6_IS_ADDR_V4MAPPED(a)) if (IN6_IS_ADDR_V4MAPPED(a))