This page describes a patch for a problem with Response Policy Zone (RPZ) NSIP and NSDAME rules observed by Andrew Fried.
RPZ including NSIP and NSDAME rules are described in Chapter 6 of the BIND 9 Administrator Reference Manual or ARM.
NSDAME rules to rewrite DNS resource records for a domain are triggered by matches of DNS server domain names for the domain. NSIP rules are triggered by IP address for those DNS server domains. To decide whether the server names or their address match, BIND must fetch or resolve them by contacting other DNS servers. Those server names and IP addresses are often required for normal operations such as sending or receiving mail or viewing web pages, but when RPZ is in use, they are first required for RPZ matching. Once they are fetched, those names and addresses are usually saved or cached.
While BIND is waiting for those server names and addresses, the original DNS client is also waiting for the response that might be rewritten by RPZ. The original client can get impatent and retransmit its request and force BIND to consider asking again for those server names and addresses. BIND should quietly discard the retransmitted request and eventually respond to the original requeset. The bug is that BIND logs a message about "db_find()failed: duplicate query" and responds to the retransmitted request with a DNS SERVFAIL error.
The following patch in the db_find_patch.txt file fixes that bug. Apply it to a BIND source tree by downloading the file and running
patch -p1 <db_find_patch.txt
diff --git a/bin/named/query.c b/bin/named/query.c index 092212e..c253f2e 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -5203,6 +5203,8 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, DNS_RPZ_DONE_IPv4); break; case DNS_R_DELEGATION: + case DNS_R_DUPLICATE: + case DNS_R_DROP: goto cleanup; case DNS_R_EMPTYNAME: case DNS_R_NXRRSET: @@ -5221,12 +5223,13 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, case ISC_R_FAILURE: rpz_rewrite_ns_skip(client, nsname, result, DNS_RPZ_DEBUG_LEVEL3, - " NS db_find()"); + " NS rpz_rrset_find() "); continue; default: rpz_rewrite_ns_skip(client, nsname, result, DNS_RPZ_INFO_LEVEL, - " unrecognized NS db_find()"); + " unrecognized NS" + " rpz_rrset_find() "); continue; } }