From 3ac34d323bbdbe99ef605a05ca44c88efa0c8bef Mon Sep 17 00:00:00 2001 From: DL6ER Date: Fri, 7 Apr 2023 18:52:15 +0200 Subject: [PATCH] Use AD bit for IN/SECURE and EDE in SERVFAIL when prox for BOGUSy-dnsmasq option is used Signed-off-by: DL6ER --- src/dnsmasq/forward.c | 2 +- src/dnsmasq_interface.c | 36 ++++++++++++++++++++++++++++++++++-- src/edns0.c | 7 +++++-- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/dnsmasq/forward.c b/src/dnsmasq/forward.c index 50fe47a9..36bf9ee9 100644 --- a/src/dnsmasq/forward.c +++ b/src/dnsmasq/forward.c @@ -782,8 +782,8 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server union all_addr a; a.log.rcode = rcode; a.log.ede = ede; - log_query(F_UPSTREAM | F_RCODE, "error", &a, NULL, 0); FTL_parse_pseudoheaders(pheader, (size_t)plen); + log_query(F_UPSTREAM | F_RCODE, "error", &a, NULL, 0); return resize_packet(header, n, pheader, plen); } diff --git a/src/dnsmasq_interface.c b/src/dnsmasq_interface.c index 61bb065b..9c70e505 100644 --- a/src/dnsmasq_interface.c +++ b/src/dnsmasq_interface.c @@ -76,6 +76,7 @@ static char *get_ptrname(struct in_addr *addr); static const char *check_dnsmasq_name(const char *name); // Static blocking metadata +static bool adbit = false; static const char *blockingreason = ""; static enum reply_type force_next_DNS_reply = REPLY_UNKNOWN; static int last_regex_idx = -1; @@ -2016,6 +2017,12 @@ static void FTL_reply(const unsigned int flags, const char *name, const union al if(config.debug & DEBUG_QUERIES) logg(" EDE: %s (%d)", edestr(addr->log.ede), addr->log.ede); } + ednsData *edns = getEDNS(); + if(edns != NULL && edns->ede != EDE_UNSET) + { + query->ede = edns->ede; + log_debug(DEBUG_QUERIES, " EDE: %s (%d)", edestr(edns->ede), edns->ede); + } // Update upstream server (if applicable) if(!cached) @@ -2182,6 +2189,13 @@ static void FTL_reply(const unsigned int flags, const char *name, const union al logg("***** Unknown upstream REPLY"); } + if(query && option_bool(OPT_DNSSEC_PROXY)) + { + // DNSSEC proxy mode is enabled. Interpret AD flag + // and set DNSSEC status accordingly + query_set_dnssec(query, adbit ? DNSSEC_SECURE : DNSSEC_INSECURE); + } + unlock_shm(); } @@ -2438,6 +2452,9 @@ static void FTL_upstream_error(const union all_addr *addr, const unsigned int fl break; } + // Get EDNS data (if available) + ednsData *edns = getEDNS(); + // Debug logging if(config.debug & DEBUG_QUERIES) { @@ -2480,8 +2497,20 @@ static void FTL_upstream_error(const union all_addr *addr, const unsigned int fl if(addr->log.ede != EDE_UNSET) // This function is only called if (flags & F_RCODE) logg(" EDE: %s (%d)", edestr(addr->log.ede), addr->log.ede); - } + if(edns != NULL && edns->ede != EDE_UNSET) + { + query->ede = edns->ede; + log_debug(DEBUG_QUERIES, " EDE: %s (%d)", edestr(edns->ede), edns->ede); + } + } + if(option_bool(OPT_DNSSEC_PROXY) && edns->ede >= EDE_DNSSEC_BOGUS && edns->ede <= EDE_NO_NSEC) + { + // DNSSEC proxy mode is enabled and we received a DNSSEC status + // from the upstream server. We need to update the DNSSEC status + // of the corresponding query. + query_set_dnssec(query, DNSSEC_BOGUS); + } // Set query reply query_set_reply(0, reply, addr, query, response); @@ -2561,6 +2590,9 @@ void _FTL_header_analysis(const unsigned char header4, const unsigned int rcode, // RA bit is not set and rcode is NXDOMAIN FTL_mark_externally_blocked(id, file, line); + // Check if AD bit is set in DNS header + adbit = header4 & HB4_AD; + // Store server which sent this reply if(server) { @@ -3300,7 +3332,7 @@ const char *get_edestr(const int ede) static void _query_set_dnssec(queriesData *query, const enum dnssec_status dnssec, const char *file, const int line) { // Return early if DNSSEC validation is disabled - if(!option_bool(OPT_DNSSEC_VALID)) + if(!option_bool(OPT_DNSSEC_VALID) && !option_bool(OPT_DNSSEC_PROXY)) return; if(config.debug & DEBUG_DNSSEC) diff --git a/src/edns0.c b/src/edns0.c index d7797b60..e7a20153 100644 --- a/src/edns0.c +++ b/src/edns0.c @@ -166,7 +166,7 @@ void FTL_parse_pseudoheaders(unsigned char *pheader, const size_t plen) // Reset EDNS(0) data memset(&edns, 0, sizeof(ednsData)); - edns.ede = -1; + edns.ede = EDE_UNSET; edns.valid = true; size_t offset; // The header is 11 bytes before the beginning of OPTION-DATA @@ -379,7 +379,10 @@ void FTL_parse_pseudoheaders(unsigned char *pheader, const size_t plen) // The INFO-CODE from the EDE EDNS option is used to // serve as an index into the "Extended DNS Error" IANA - // registry, the initial values for which are defined in + // registry, the initial values for which are defined in + // this document. The value of the INFO-CODE is encoded + // as a two-octet unsigned integer in network byte + // order. edns.ede = ntohs(((int)p[1] << 8) | p[0]); if(config.debug & DEBUG_EDNS0) logg("EDNS(0) EDE: %s (code %d)", edestr(edns.ede), edns.ede);