From: Mark Andrews Date: Tue, 23 May 2023 06:59:40 +0000 (+1000) Subject: Use NS rather than A records for qname-minimization relaxed X-Git-Tag: v9.19.15~14^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dd00b3c50b6d173b90208c5f659c9ca55a55dd2e;p=thirdparty%2Fbind9.git Use NS rather than A records for qname-minimization relaxed Remove all references to DNS_FETCHOPT_QMIN_USE_A and adjust the expected tests results in the qmin system test. --- diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh index 6744c1aa781..eb551f98b92 100644 --- a/bin/tests/system/digdelv/tests.sh +++ b/bin/tests/system/digdelv/tests.sh @@ -1425,7 +1425,6 @@ if [ -x "$DELV" ] ; then ret=0 delv_with_opts -i +ns +qmin +hint=../common/root.hint a a.example > delv.out.test$n || ret=1 grep -q '; authoritative' delv.out.test$n || ret=1 - grep -q '_.example' delv.out.test$n || ret=1 if [ $ret -ne 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -1443,7 +1442,6 @@ if [ -x "$DELV" ] ; then ret=0 delv_with_opts -a ns1/anchor.dnskey +root +ns +qmin +hint=../common/root.hint a a.example > delv.out.test$n || ret=1 grep -q '; fully validated' delv.out.test$n || ret=1 - grep -q '_.example' delv.out.test$n || ret=1 if [ $ret -ne 0 ]; then echo_i "failed"; fi status=$((status+ret)) diff --git a/bin/tests/system/qmin/tests.sh b/bin/tests/system/qmin/tests.sh index 26d3cb8946c..12d74518fcd 100755 --- a/bin/tests/system/qmin/tests.sh +++ b/bin/tests/system/qmin/tests.sh @@ -154,20 +154,20 @@ grep "icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.1" dig.out.test$n > / sleep 1 sort ans2/query.log > ans2/query.log.sorted cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1 -ADDR _.boing.good. -ADDR _.zoop.boing.good. ADDR a.bit.longer.ns.name.good. ADDR a.bit.longer.ns.name.good. ADDR ns2.good. ADDR ns3.good. ADDR ns3.good. +NS boing.good. +NS zoop.boing.good. __EOF cat << __EOF | diff ans3/query.log - > /dev/null || ret=1 -ADDR _.ptang.zoop.boing.good. -ADDR _.icky.ptang.zoop.boing.good. +NS ptang.zoop.boing.good. +NS icky.ptang.zoop.boing.good. __EOF cat << __EOF | diff ans4/query.log - > /dev/null || ret=1 -ADDR _.icky.icky.ptang.zoop.boing.good. +NS icky.icky.ptang.zoop.boing.good. ADDR icky.icky.icky.ptang.zoop.boing.good. __EOF for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done @@ -203,20 +203,18 @@ grep "icky.icky.icky.ptang.zoop.boing.bad. 1 IN A 192.0.2.1" dig.out.test$n > /d sleep 1 sort ans2/query.log > ans2/query.log.sorted cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1 -ADDR _.boing.bad. -ADDR _.zoop.boing.bad. ADDR a.bit.longer.ns.name.bad. ADDR a.bit.longer.ns.name.bad. +ADDR icky.icky.icky.ptang.zoop.boing.bad. ADDR ns2.bad. ADDR ns3.bad. ADDR ns3.bad. +NS boing.bad. __EOF cat << __EOF | diff ans3/query.log - > /dev/null || ret=1 -ADDR _.ptang.zoop.boing.bad. -ADDR _.icky.ptang.zoop.boing.bad. +ADDR icky.icky.icky.ptang.zoop.boing.bad. __EOF cat << __EOF | diff ans4/query.log - > /dev/null || ret=1 -ADDR _.icky.icky.ptang.zoop.boing.bad. ADDR icky.icky.icky.ptang.zoop.boing.bad. __EOF for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done @@ -251,16 +249,15 @@ $DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.ugly. @10.53.0.7 > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 grep "icky.icky.icky.ptang.zoop.boing.ugly. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1 sleep 1 - sort ans2/query.log > ans2/query.log.sorted cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1 -ADDR _.boing.ugly. ADDR a.bit.longer.ns.name.ugly. ADDR a.bit.longer.ns.name.ugly. ADDR icky.icky.icky.ptang.zoop.boing.ugly. ADDR ns2.ugly. ADDR ns3.ugly. ADDR ns3.ugly. +NS boing.ugly. __EOF echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans3/query.log - > /dev/null || ret=1 echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans4/query.log - > /dev/null || ret=1 @@ -270,7 +267,7 @@ status=$((status+ret)) $RNDCCMD 10.53.0.7 flush n=$((n+1)) -echo_i "information that minimization was unsuccessful for .ugly is logged ($n)" +echo_i "information that minimization was unsuccessful for .ugly is logged in relaxed mode ($n)" ret=0 wait_for_log 5 "success resolving 'icky.icky.icky.ptang.zoop.boing.ugly/A' after disabling qname minimization" ns7/named.run > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi @@ -458,9 +455,9 @@ grep "a\.b\.stale\..*1.*IN.*TXT.*hooray" dig.out.test$n > /dev/null || ret=1 sleep 1 sort ans2/query.log > ans2/query.log.sorted cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1 -ADDR _.b.stale. ADDR ns.b.stale. ADDR ns2.stale. +NS b.stale. __EOF test -f ans3/query.log && ret=1 sort ans4/query.log > ans4/query.log.sorted @@ -523,7 +520,7 @@ grep "a\.b\.stale\..*1.*IN.*TXT.*hooray" dig.out.test$n > /dev/null || ret=1 sleep 1 sort ans2/query.log > ans2/query.log.sorted cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1 -ADDR _.b.stale. +NS b.stale. __EOF test -f ans3/query.log && ret=1 sort ans4/query.log > ans4/query.log.sorted diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index ff400de38dd..f1a3c9e1916 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -1392,21 +1392,22 @@ default is used. :tags: query :short: Controls QNAME minimization behavior in the BIND 9 resolver. - When this is set to ``strict``, BIND follows the QNAME - minimization algorithm to the letter, as specified in :rfc:`7816`. + When this is set to ``strict``, BIND follows the QNAME minimization + algorithm to the letter, as specified in :rfc:`7816`. Setting this option to ``relaxed`` causes BIND to fall back to - normal (non-minimized) query mode when it receives either NXDOMAIN or - other unexpected responses (e.g., SERVFAIL, improper zone cut, - REFUSED) to a minimized query. A resolver can use a leading - underscore, like ``_.example.com``, in an attempt to improve - interoperability. (See :rfc:`7816` section 3.) + normal (non-minimized) query mode when it receives either NXDOMAIN + or other unexpected responses (e.g., SERVFAIL, improper zone + cut, REFUSED) to a minimized query. + + In ``relaxed`` mode ``named`` makes NS queries for ```` as it + walks down the tree. ``disabled`` disables QNAME minimization completely. ``off`` is a synonym for ``disabled``. - The current default is ``relaxed``, but it - may be changed to ``strict`` in a future release. + The current default is ``relaxed``, but it may be changed to + ``strict`` in a future release. .. namedconf:statement:: tkey-gssapi-keytab :tags: security diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index 83ea6bb4062..d094f58d846 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -120,31 +120,21 @@ typedef enum { dns_quotatype_zone = 0, dns_quotatype_server } dns_quotatype_t; /* RESERVED ECS 0x00001000 */ /* RESERVED ECS 0x00002000 */ /* RESERVED TCPCLIENT 0x00004000 */ -#define DNS_FETCHOPT_NOCACHED 0x00008000 /*%< Force cache update. */ -#define DNS_FETCHOPT_QMINIMIZE \ - 0x00010000 /*%< Use qname \ - * minimization. */ -#define DNS_FETCHOPT_NOFOLLOW \ - 0x00020000 /*%< Don't follow \ - * delegations */ -#define DNS_FETCHOPT_QMIN_STRICT \ - 0x00040000 /*%< Do not work around \ - * servers that return \ - * errors on non-empty \ - * terminals. */ -#define DNS_FETCHOPT_QMIN_USE_A \ - 0x00080000 /*%< Use A type queries \ - * instead of NS when \ - * doing minimization */ -#define DNS_FETCHOPT_QMIN_SKIP_IP6A \ - 0x00100000 /*%< Skip some labels \ - * when doing qname \ - * minimization on \ +#define DNS_FETCHOPT_NOCACHED 0x00008000 /*%< Force cache update. */ +#define DNS_FETCHOPT_QMINIMIZE 0x00010000 /*%< Use qname minimization. */ +#define DNS_FETCHOPT_NOFOLLOW \ + 0x00020000 /*%< Don't retrieve the NS RRset from the child zone when a \ + * delegation is returned in response to a NS query. */ +#define DNS_FETCHOPT_QMIN_STRICT \ + 0x00040000 /*%< Do not work around servers that return errors on \ + * non-empty terminals. */ +#define DNS_FETCHOPT_QMIN_SKIP_IP6A \ + 0x00080000 /*%< Skip some labels when doing qname minimization on \ * ip6.arpa. */ -#define DNS_FETCHOPT_NOFORWARD \ - 0x00200000 /*%< Do not use forwarders \ - * if possible. */ +#define DNS_FETCHOPT_NOFORWARD \ + 0x00100000 /*%< Do not use forwarders if possible. */ +/* UNUSED 0x00200000 */ /* Reserved in use by adb.c 0x00400000 */ #define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000 #define DNS_FETCHOPT_EDNSVERSIONMASK 0xff000000 diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 28561e3ca12..c747551881c 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -635,11 +635,6 @@ static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 }; static const dns_name_t ip6_arpa = DNS_NAME_INITABSOLUTE(ip6_arpa_data, ip6_arpa_offsets); -static unsigned char underscore_data[] = "\001_"; -static unsigned char underscore_offsets[] = { 0 }; -static const dns_name_t underscore_name = - DNS_NAME_INITNONABSOLUTE(underscore_data, underscore_offsets); - static void dns_resolver__destroy(dns_resolver_t *res); static isc_result_t @@ -4056,11 +4051,14 @@ fctx_try(fetchctx_t *fctx, bool retrying, bool badcache) { } /* - * In "_ A" mode we're asking for _.domain - - * resolver by default will follow delegations - * then, we don't want that. + * Turn on NOFOLLOW in relaxed mode so that QNAME minimisation + * doesn't cause additional queries to resolve the target of the + * QNAME minimisation request when a referral is returned. This + * will also reduce the impact of mis-matched NS RRsets where + * the child's NS RRset is garbage. If a delegation is + * discovered DNS_R_DELEGATION will be returned to resume_qmin. */ - if ((options & DNS_FETCHOPT_QMIN_USE_A) != 0) { + if ((options & DNS_FETCHOPT_QMIN_STRICT) == 0) { options |= DNS_FETCHOPT_NOFOLLOW; } @@ -4154,14 +4152,6 @@ resume_qmin(void *arg) { goto cleanup; case DNS_R_NXDOMAIN: case DNS_R_NCACHENXDOMAIN: - /* - * If we're doing "_ A"-style minimization we can get - * NX answer to minimized query - we need to continue then. - */ - if ((fctx->options & DNS_FETCHOPT_QMIN_USE_A) != 0) { - break; - } - FALLTHROUGH; case DNS_R_FORMERR: case DNS_R_REMOTEFORMERR: case ISC_R_FAILURE: @@ -4180,6 +4170,11 @@ resume_qmin(void *arg) { } break; default: + /* + * When DNS_FETCHOPT_NOFOLLOW is set and a delegation + * was discovered, DNS_R_DELEGATION is returned and is + * processed here. + */ break; } @@ -7630,7 +7625,8 @@ resquery_response(isc_result_t eresult, isc_region_t *region, void *arg) { case DNS_R_CHASEDSSERVERS: break; case DNS_R_DELEGATION: - /* With NOFOLLOW we want to pass the result code + /* + * With NOFOLLOW we want to pass the result code. */ if ((fctx->options & DNS_FETCHOPT_NOFOLLOW) == 0) { result = ISC_R_SUCCESS; @@ -10200,24 +10196,8 @@ fctx_minimize_qname(fetchctx_t *fctx) { dns_fixedname_t fname; dns_name_t *name = dns_fixedname_initname(&fname); dns_name_split(fctx->name, fctx->qmin_labels, NULL, name); - if ((fctx->options & DNS_FETCHOPT_QMIN_USE_A) != 0) { - isc_buffer_t dbuf; - dns_fixedname_t tmpname; - dns_name_t *tname = dns_fixedname_initname(&tmpname); - char ndata[DNS_NAME_MAXWIRE]; - - isc_buffer_init(&dbuf, ndata, DNS_NAME_MAXWIRE); - dns_fixedname_init(&tmpname); - result = dns_name_concatenate(&underscore_name, name, - tname, &dbuf); - if (result == ISC_R_SUCCESS) { - dns_name_copy(tname, fctx->qminname); - } - fctx->qmintype = dns_rdatatype_a; - } else { - dns_name_copy(name, fctx->qminname); - fctx->qmintype = dns_rdatatype_ns; - } + dns_name_copy(name, fctx->qminname); + fctx->qmintype = dns_rdatatype_ns; fctx->minimized = true; } else { /* Minimization is done, we'll ask for whole qname */ diff --git a/lib/ns/query.c b/lib/ns/query.c index 3d5752c8e5c..18c34b6968c 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -12072,8 +12072,6 @@ ns_query_start(ns_client_t *client, isc_nmhandle_t *handle) { DNS_FETCHOPT_QMIN_SKIP_IP6A; if (client->view->qmin_strict) { client->query.fetchoptions |= DNS_FETCHOPT_QMIN_STRICT; - } else { - client->query.fetchoptions |= DNS_FETCHOPT_QMIN_USE_A; } }