diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index 0ae46a4..1eba6fa 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -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 with "no such domain" rather than being forwarded upstream. The 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 .B \-V, --alias=[]|[-],[,] Modify IPv4 addresses returned from upstream nameservers; old-ip is diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 8200e1d..8b2513e 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -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 in_arpa_name_2_addr(char *namein, union all_addr *addrp); int private_net(struct in_addr addr, int ban_localhost); +int private_net6(struct in6_addr *a, int ban_localhost); /* extract_name ops */ #define EXTR_NAME_EXTRACT 1 #define EXTR_NAME_COMPARE 2 diff --git a/src/dnssec.c b/src/dnssec.c index 9712034..0860daa 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -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 (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); neganswer = 1; diff --git a/src/rfc1035.c b/src/rfc1035.c index 0a6d7f4..f664121 100644 --- a/src/rfc1035.c +++ b/src/rfc1035.c @@ -424,7 +424,7 @@ int private_net(struct in_addr addr, int ban_localhost) ((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 */ if (IN6_IS_ADDR_V4MAPPED(a))