From c786c578d7256d18050b0315dcadb4429abad0b1 Mon Sep 17 00:00:00 2001 From: Diego Fronza Date: Mon, 2 Mar 2020 14:52:10 -0300 Subject: [PATCH 1/5] Added RPZ configuration option "nsdname-wait-recurse" This new option was added to fill a gap in RPZ configuration options. It was possible to instruct BIND wheter NSIP rewritting rules would apply or not, as long as the required data was already in cache or not, respectively, by means of the option nsip-wait-recurse. A value of yes (default) could incur a little processing cost, since BIND would need to recurse to find NS addresses in case they were not in the cache. This behavior could be changed by setting nsip-wait-recurse value to no, in which case BIND would promptly return some error code if the NS IP addresses data were not in cache, then BIND would start a recursive query in background, so future similar requests would have the required data (NS IPs) in cache, allowing BIND to apply NSIP rules accordingly. A similar feature wasn't available for NSDNAME triggers, so this commit adds the option nsdname-wait-recurse to fill this gap, as it was expected by couple BIND users. --- bin/named/server.c | 7 +++++++ lib/dns/include/dns/rpz.h | 1 + lib/isccfg/namedconf.c | 1 + lib/ns/query.c | 5 ++++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/bin/named/server.c b/bin/named/server.c index 781d9e013d..2836429de3 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -2557,6 +2557,13 @@ configure_rpz(dns_view_t *view, const cfg_obj_t **maps, zones->p.qname_wait_recurse = false; } + sub_obj = cfg_tuple_get(rpz_obj, "nsdname-wait-recurse"); + if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { + zones->p.nsdname_wait_recurse = true; + } else { + zones->p.nsdname_wait_recurse = false; + } + sub_obj = cfg_tuple_get(rpz_obj, "nsip-wait-recurse"); if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { zones->p.nsip_wait_recurse = true; diff --git a/lib/dns/include/dns/rpz.h b/lib/dns/include/dns/rpz.h index 4e834d7fe4..966aaee0ed 100644 --- a/lib/dns/include/dns/rpz.h +++ b/lib/dns/include/dns/rpz.h @@ -203,6 +203,7 @@ struct dns_rpz_popt { bool break_dnssec; bool qname_wait_recurse; bool nsip_wait_recurse; + bool nsdname_wait_recurse; unsigned int min_ns_labels; dns_rpz_num_t num_zones; }; diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index d3b0d6a41f..55e16c997b 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -1736,6 +1736,7 @@ static cfg_tuplefielddef_t rpz_fields[] = { { "min-update-interval", &cfg_type_duration, 0 }, { "min-ns-dots", &cfg_type_uint32, 0 }, { "nsip-wait-recurse", &cfg_type_boolean, 0 }, + { "nsdname-wait-recurse", &cfg_type_boolean, 0 }, { "qname-wait-recurse", &cfg_type_boolean, 0 }, { "recursive-only", &cfg_type_boolean, 0 }, { "nsip-enable", &cfg_type_boolean, 0 }, diff --git a/lib/ns/query.c b/lib/ns/query.c index 482b3f3b01..a503109db0 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -2826,7 +2826,10 @@ rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type, */ if (rpz_type == DNS_RPZ_TYPE_IP) { result = DNS_R_NXRRSET; - } else if (!client->view->rpzs->p.nsip_wait_recurse) { + } else if (!client->view->rpzs->p.nsip_wait_recurse || + (!client->view->rpzs->p.nsdname_wait_recurse && + rpz_type == DNS_RPZ_TYPE_NSDNAME)) + { query_rpzfetch(client, name, type); result = DNS_R_NXRRSET; } else { From fe1011152156f92773d8b9038147351926d87f74 Mon Sep 17 00:00:00 2001 From: Diego Fronza Date: Mon, 2 Mar 2020 15:16:34 -0300 Subject: [PATCH 2/5] Added test for nsdname-wait-recurse option --- bin/tests/system/rpzrecurse/clean.sh | 2 +- .../system/rpzrecurse/ns3/named3.conf.in | 38 +++++++++++++++++++ bin/tests/system/rpzrecurse/setup.sh | 1 - bin/tests/system/rpzrecurse/tests.sh | 38 +++++++++++++++++-- 4 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 bin/tests/system/rpzrecurse/ns3/named3.conf.in diff --git a/bin/tests/system/rpzrecurse/clean.sh b/bin/tests/system/rpzrecurse/clean.sh index ffd9dfd50a..9117a241eb 100644 --- a/bin/tests/system/rpzrecurse/clean.sh +++ b/bin/tests/system/rpzrecurse/clean.sh @@ -22,7 +22,7 @@ rm -f ns2/*.queries rm -f ns2/named.[0-9]*.conf rm -f ns2/named.conf.header -rm -f ns3/named2.conf +rm -f ns3/named.conf rm -f dnsrps*.conf dnsrpzd* rm -f ns*/session.key diff --git a/bin/tests/system/rpzrecurse/ns3/named3.conf.in b/bin/tests/system/rpzrecurse/ns3/named3.conf.in new file mode 100644 index 0000000000..73470fafbd --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns3/named3.conf.in @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../common/rndc.key"; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + response-policy { zone "policy"; } nsdname-wait-recurse no + nsdname-enable yes; + + include "../dnsrps.conf"; +}; + +zone "policy" { type master; file "policy.db"; }; + +zone "example.tld" { type master; file "example.db"; }; + +zone "." { type master; file "root.db"; }; diff --git a/bin/tests/system/rpzrecurse/setup.sh b/bin/tests/system/rpzrecurse/setup.sh index 36786a72de..9ab709fc9d 100644 --- a/bin/tests/system/rpzrecurse/setup.sh +++ b/bin/tests/system/rpzrecurse/setup.sh @@ -42,7 +42,6 @@ copy_setports ns2/named.conf.header.in ns2/named.conf.header copy_setports ns2/named.default.conf ns2/named.conf copy_setports ns3/named1.conf.in ns3/named.conf -copy_setports ns3/named2.conf.in ns3/named2.conf copy_setports ns4/named.conf.in ns4/named.conf diff --git a/bin/tests/system/rpzrecurse/tests.sh b/bin/tests/system/rpzrecurse/tests.sh index 3679d35c8f..ca63987d0f 100644 --- a/bin/tests/system/rpzrecurse/tests.sh +++ b/bin/tests/system/rpzrecurse/tests.sh @@ -493,10 +493,10 @@ for mode in native dnsrps; do $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a > dig.out.yes.$t t2=`$PERL -e 'print time()."\n";'` p1=`expr $t2 - $t1` - echo_i "elasped time $p1 seconds" + echo_i "elapsed time $p1 seconds" $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush - cp -f ns3/named2.conf ns3/named.conf + copy_setports ns3/named2.conf.in ns3/named.conf $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload > /dev/null echo_i "timing 'nsip-wait-recurse no'" @@ -504,12 +504,44 @@ for mode in native dnsrps; do $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a > dig.out.no.$t t4=`$PERL -e 'print time()."\n";'` p2=`expr $t4 - $t3` - echo_i "elasped time $p2 seconds" + echo_i "elapsed time $p2 seconds" if test $p1 -le $p2; then ret=1; fi if test $ret != 0; then echo_i "failed"; fi status=`expr $status + $ret` + $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush + # restore original named.conf + copy_setports ns3/named1.conf.in ns3/named.conf + $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload > /dev/null + + t=`expr $t + 1` + echo_i "checking 'nsdname-wait-recurse no' is faster than 'nsdname-wait-recurse yes' ($t)" + add_test_marker 10.53.0.2 + echo_i "timing 'nsdname-wait-recurse yes' (default)" + ret=0 + t1=`$PERL -e 'print time()."\n";'` + $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a > dig.out.yes.$t + t2=`$PERL -e 'print time()."\n";'` + p1=`expr $t2 - $t1` + echo_i "elapsed time $p1 seconds" + + $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush + copy_setports ns3/named3.conf.in ns3/named.conf + $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload > /dev/null + + echo_i "timing 'nsdname-wait-recurse no'" + t3=`$PERL -e 'print time()."\n";'` + $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a > dig.out.no.$t + t4=`$PERL -e 'print time()."\n";'` + p2=`expr $t4 - $t3` + echo_i "elapsed time $p2 seconds" + + if test $p1 -le $p2; then ret=1; fi + if test $ret != 0; then echo_i "failed"; fi + status=`expr $status + $ret` + + [ $status -ne 0 ] && pf=fail || pf=pass case $mode in native) From 2822b01636fa97c2e2cf7ef25e04e81864b0a335 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Thu, 12 Mar 2020 00:28:26 -0700 Subject: [PATCH 3/5] incidental fix: dnsrps test was failing the test for logging of invalid prefixes doesn't work when running with dnsrps; disable it in that case. --- bin/tests/system/rpzrecurse/tests.sh | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/bin/tests/system/rpzrecurse/tests.sh b/bin/tests/system/rpzrecurse/tests.sh index ca63987d0f..7b1f206389 100644 --- a/bin/tests/system/rpzrecurse/tests.sh +++ b/bin/tests/system/rpzrecurse/tests.sh @@ -474,15 +474,17 @@ for mode in native dnsrps; do status=1 } - # Check for invalid prefix length error - t=`expr $t + 1` - echo_i "testing for invalid prefix length error (${t})" - add_test_marker 10.53.0.2 - run_server invalidprefixlength - grep "invalid rpz IP address \"1000.4.0.53.10.rpz-client-ip.invalidprefixlength\"; invalid prefix length of 1000$" ns2/named.run > /dev/null || { - echo_ic "failed: expected that invalid prefix length error would be logged" - status=1 - } + if [ "$mode" = "native" ]; then + # Check for invalid prefix length error + t=`expr $t + 1` + echo_i "testing for invalid prefix length error (${t})" + add_test_marker 10.53.0.2 + run_server invalidprefixlength + grep "invalid rpz IP address \"1000.4.0.53.10.rpz-client-ip.invalidprefixlength\"; invalid prefix length of 1000$" ns2/named.run > /dev/null || { + echo_ic "failed: expected that invalid prefix length error would be logged" + status=1 + } + fi t=`expr $t + 1` echo_i "checking 'nsip-wait-recurse no' is faster than 'nsip-wait-recurse yes' ($t)" From 4e8f8da6611d5dd93d058a4bb262085a85e128cf Mon Sep 17 00:00:00 2001 From: Diego Fronza Date: Wed, 11 Mar 2020 16:58:36 -0300 Subject: [PATCH 4/5] Added nsdname-wait-recurse documentation to ARM --- doc/arm/Bv9ARM-book.xml | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 6fc046e950..e291dc88d0 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -9843,18 +9843,36 @@ deny-answer-aliases { "example.net"; }; NSDNAME triggers match names of authoritative servers - for the query name, a parent of the query name, a CNAME for - query name, or a parent of a CNAME. - They are encoded as subdomains of - rpz-nsdname relativized - to the RPZ origin name. - NSIP triggers match IP addresses in A and - AAAA RRsets for domains that can be checked against NSDNAME - policy records. - The nsdname-enable phrase turns NSDNAME + for the query name, a parent of the query name, a CNAME + for query name, or a parent of a CNAME. They are + encoded as subdomains of rpz-nsdname + relativized to the RPZ origin name. NSIP triggers match + IP addresses in A and AAAA RRsets for domains that can + be checked against NSDNAME policy records. The + nsdname-enable phrase turns NSDNAME triggers off or on for a single policy zone or all zones. + + If authoritative nameservers for the query name are not + yet known, named will recursively + look up the authoritative servers for the query name + before applying an RPZ-NSDNAME rule. + This can cause a processing delay. To speed up + processing at the cost of precision, the + nsdname-wait-recurse option + can be used: when set to no, + RPZ-NSDNAME rules will only be applied when authoritative + servers for the query name have already been looked up and + cached. If authoritative servers for the query name + are not in the cache, then the RPZ-NSDNAME rule will be + ignored, but the authoritative servers for the query name + will be looked up in the background, and the rule will be + applied to subsequent queries. The default is + yes, meaning RPZ-NSDNAME + rules should always be applied even if authoritative + servers for the query name need to be looked up first. + From 267e2c47725f5aa5a3f009819fb44b856d651c29 Mon Sep 17 00:00:00 2001 From: Diego Fronza Date: Wed, 11 Mar 2020 16:32:47 -0300 Subject: [PATCH 5/5] Add CHANGES and release note --- CHANGES | 5 +++++ doc/arm/notes-9.17.0.xml | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/CHANGES b/CHANGES index 01ec0b7b26..a0ceea14bb 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +5369. [func] Add the ability to specify whether or not to wait + for nameserver domain names to be looked up, with + a new RPZ modifying directive 'nsdname-wait-recurse'. + [GL #1138] + 5368. [bug] Named failed to restart if 'rndc addzone' names contained special characters (e.g. '/'). [GL #1655] diff --git a/doc/arm/notes-9.17.0.xml b/doc/arm/notes-9.17.0.xml index 7f0227a95b..5234ccec7e 100644 --- a/doc/arm/notes-9.17.0.xml +++ b/doc/arm/notes-9.17.0.xml @@ -49,6 +49,19 @@ 100%. [GL #1515] + + + A new RPZ option nsdname-wait-recurse + controls whether RPZ-NSDNAME rules should always be applied + even if the names of authoritative name servers for the query + name need to be looked up recurively first. The default is + yes. Setting it to + no speeds up initial responses by skipping + RPZ-NSDNAME rules when name server domain names are not yet + in the cache. The names will be looked up in the background and + the rule will be applied for subsequent queries. [GL #1138] + +