]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] minimal-any
authorEvan Hunt <each@isc.org>
Wed, 25 May 2016 20:54:34 +0000 (13:54 -0700)
committerEvan Hunt <each@isc.org>
Wed, 25 May 2016 20:54:34 +0000 (13:54 -0700)
4371. [func] New "minimal-any" option reduces the size of UDP
responses for qtype ANY by returning a single
arbitrarily selected RRset instead of all RRsets.
Thanks to Tony Finch. [RT #41615]

12 files changed:
CHANGES
bin/named/config.c
bin/named/named.conf.docbook
bin/named/query.c
bin/named/server.c
bin/tests/system/additional/ns1/named3.conf [new file with mode: 0644]
bin/tests/system/additional/tests.sh
doc/arm/Bv9ARM-book.xml
doc/arm/notes.xml
lib/dns/include/dns/view.h
lib/dns/view.c
lib/isccfg/namedconf.c

diff --git a/CHANGES b/CHANGES
index dee6211117401905f51900c02c2976ea1cc85649..849f5716af5aeb3e30a2536992731895111ecedd 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+4371.  [func]          New "minimal-any" option reduces the size of UDP
+                       responses for qtype ANY by returning a single
+                       arbitrarily selected RRset instead of all RRsets.
+                       Thanks to Tony Finch. [RT #41615]
+
 4370.  [bug]           Address python3 compatibility issues with RNDC module.
                        [RT #42499]
 
index b0af1be2c37bb24bd1dacca40ffde2c287e12e61..43c253e30a49f6e44c00abe9026b842de6becb7f 100644 (file)
@@ -141,6 +141,7 @@ options {\n\
 #      sortlist <none>\n\
 #      topology <none>\n\
        auth-nxdomain false;\n\
+       minimal-any false;\n\
        minimal-responses false;\n\
        recursion true;\n\
        provide-ixfr true;\n\
index bd7bb4057e6f55a2d6853f71c26de2780ea0ab38..b919a628c76b23c3e64d35fe04a4a3fe3d06be4d 100644 (file)
@@ -248,6 +248,7 @@ options {
        sortlist { <replaceable>address_match_element</replaceable>; ... };
        topology { <replaceable>address_match_element</replaceable>; ... }; // not implemented
        auth-nxdomain <replaceable>boolean</replaceable>; // default changed
+       minimal-any <replaceable>boolean</replaceable>;
        minimal-responses <replaceable>boolean</replaceable>;
        recursion <replaceable>boolean</replaceable>;
        rrset-order {
@@ -446,6 +447,7 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
        sortlist { <replaceable>address_match_element</replaceable>; ... };
        topology { <replaceable>address_match_element</replaceable>; ... }; // not implemented
        auth-nxdomain <replaceable>boolean</replaceable>; // default changed
+       minimal-any <replaceable>boolean</replaceable>;
        minimal-responses <replaceable>boolean</replaceable>;
        recursion <replaceable>boolean</replaceable>;
        rrset-order {
index faa39d63545b0e612e564fcab306e7b64048f504..599de05d9218d053e654a392af1451ea969a49bc 100644 (file)
@@ -8339,6 +8339,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
 #endif
 
        if (type == dns_rdatatype_any) {
+               /*
+                * For minimal-any, we only add records that
+                * match this type or cover this type.
+                */
+               dns_rdatatype_t onetype = 0;
 #ifdef ALLOW_FILTER_AAAA
                isc_boolean_t have_aaaa, have_a, have_sig;
 
@@ -8402,6 +8407,21 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                                 * ANY queries.
                                 */
                                dns_rdataset_disassociate(rdataset);
+                       } else if (client->view->minimal_any &&
+                                  !TCP(client) && !WANTDNSSEC(client) &&
+                                  qtype == dns_rdatatype_any &&
+                                  (rdataset->type == dns_rdatatype_sig ||
+                                   rdataset->type == dns_rdatatype_rrsig)) {
+                               CTRACE(ISC_LOG_DEBUG(5), "query_find: "
+                                      "minimal-any skip signature");
+                               dns_rdataset_disassociate(rdataset);
+                       } else if (client->view->minimal_any &&
+                                  !TCP(client) && onetype != 0 &&
+                                  rdataset->type != onetype &&
+                                  rdataset->covers != onetype) {
+                               CTRACE(ISC_LOG_DEBUG(5), "query_find: "
+                                      "minimal-any skip rdataset");
+                               dns_rdataset_disassociate(rdataset);
                        } else if ((qtype == dns_rdatatype_any ||
                             rdataset->type == qtype) && rdataset->type != 0) {
 #ifdef ALLOW_FILTER_AAAA
@@ -8421,6 +8441,15 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                                        name = (fname != NULL) ? fname : tname;
                                        query_prefetch(client, name, rdataset);
                                }
+                               /*
+                                * Remember the first RRtype we find so we
+                                * can skip others with minimal-any.
+                                */
+                               if (rdataset->type == dns_rdatatype_sig ||
+                                   rdataset->type == dns_rdatatype_rrsig)
+                                       onetype = rdataset->covers;
+                               else
+                                       onetype = rdataset->type;
                                query_addrrset(client,
                                               fname != NULL ? &fname : &tname,
                                               &rdataset, NULL,
@@ -9096,6 +9125,14 @@ ns_query_start(ns_client_t *client) {
                client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
                                             NS_QUERYATTR_NOADDITIONAL);
 
+       /*
+        * Maybe turn on minimal responses for ANY queries.
+        */
+       if (qtype == dns_rdatatype_any &&
+           client->view->minimal_any && !TCP(client))
+               client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
+                                            NS_QUERYATTR_NOADDITIONAL);
+
        /*
         * Turn on minimal responses for EDNS/UDP bufsize 512 queries.
         */
index c622a0fc56f04d06dada73e05a777878d8d8b1d9..f06678d078915786157aecb9acc79c6a939c31a1 100644 (file)
@@ -3545,6 +3545,11 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
        INSIST(result == ISC_R_SUCCESS);
        view->auth_nxdomain = cfg_obj_asboolean(obj);
 
+       obj = NULL;
+       result = ns_config_get(maps, "minimal-any", &obj);
+       INSIST(result == ISC_R_SUCCESS);
+       view->minimal_any = cfg_obj_asboolean(obj);
+
        obj = NULL;
        result = ns_config_get(maps, "minimal-responses", &obj);
        INSIST(result == ISC_R_SUCCESS);
diff --git a/bin/tests/system/additional/ns1/named3.conf b/bin/tests/system/additional/ns1/named3.conf
new file mode 100644 (file)
index 0000000..52f21b8
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+options {
+       query-source address 10.53.0.1;
+       notify-source 10.53.0.1;
+       transfer-source 10.53.0.1;
+       recursion no;
+       additional-from-auth no;
+       port 5300;
+       pid-file "named.pid";
+       listen-on { 10.53.0.1; };
+       listen-on-v6 { none; };
+       notify no;
+       minimal-any yes;
+};
+
+include "../../common/rndc.key";
+
+controls {
+       inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "rt.example" {
+       type master;
+       file "rt.db";
+};
index 70ebbe5505eff3d7a99e76bfbc4d5c7e99055f92..51e4ded31b117d3dc153688cc6ee3da20c7d60c9 100644 (file)
@@ -118,4 +118,25 @@ echo "I:testing with 'minimal-responses no;'"
 minimal=no
 dotests
 
+echo "I:testing with 'minimal-any no;'"
+n=`expr $n + 1`
+$DIG -t ANY www.rt.example @10.53.0.1 -p 5300 > dig.out.$n || ret=1
+grep "ANSWER: 3, AUTHORITY: 1, ADDITIONAL: 2" dig.out.$n > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+    echo "I: failed"; status=1
+fi
+
+echo "I:reconfiguring server"
+cp ns1/named3.conf ns1/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 reconfig 2>&1 | sed 's/^/I:ns1 /'
+sleep 2
+
+echo "I:testing with 'minimal-any yes;'"
+n=`expr $n + 1`
+$DIG -t ANY www.rt.example @10.53.0.1 -p 5300 > dig.out.$n || ret=1
+grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" dig.out.$n > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+    echo "I: failed"; status=1
+fi
+
 exit $status
index 427c14967e4bdfe3e79efb6c56473ca84d6efb40..d14538e79b19513554943140a1f0159da5bc0bc6 100644 (file)
@@ -4438,6 +4438,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
     <optional> has-old-clients <replaceable>yes_or_no</replaceable>; </optional>
     <optional> host-statistics <replaceable>yes_or_no</replaceable>; </optional>
     <optional> host-statistics-max <replaceable>number</replaceable>; </optional>
+    <optional> minimal-any <replaceable>yes_or_no</replaceable>; </optional>
     <optional> minimal-responses <replaceable>yes_or_no</replaceable>; </optional>
     <optional> multiple-cnames <replaceable>yes_or_no</replaceable>; </optional>
     <optional> notify <replaceable>yes_or_no</replaceable> | <replaceable>explicit</replaceable> | <replaceable>master-only</replaceable>; </optional>
@@ -6196,6 +6197,30 @@ options {
              </listitem>
            </varlistentry>
 
+           <varlistentry>
+             <term><command>minimal-any</command></term>
+             <listitem>
+               <para>
+                 If set to <userinput>yes</userinput>, then when
+                 generating a positive response to a query of type
+                 ANY over UDP, the server will reply with only one
+                 of the RRsets for the query name, and its covering
+                 RRSIGs if any, instead of replying with all known
+                 RRsets for the name.  Similarly, a query for type
+                 RRSIG will be answered with the RRSIG records covering
+                 only one type. This can reduce the impact of some kinds
+                 of attack traffic, without harming legitimate
+                 clients.  (Note, however, that the RRset returned is the
+                 first one found in the database; it is not necessarily
+                 the smallest available RRset.)
+                 Additionally, <option>minimal-responses</option> is
+                 turned on for these queries, so no unnecessary records
+                 will be added to the authority or additional sections.
+                 The default is <userinput>no</userinput>.
+               </para>
+           </listitem>
+         </varlistentry>
+
            <varlistentry>
              <term><command>multiple-cnames</command></term>
              <listitem>
index e0eb3bd2f44b06507680e04c8294f442f47b9f52..4e7341d5d680a7114fdb387c6794ea45e7afb2c7 100644 (file)
          when a system's clock needs to be reset backwards.
        </para>
       </listitem>
+      <listitem>
+       <para>
+         The new <command>minimal-any</option> reduces the size of
+         answers to UDP queries for type ANY by implementing one of
+         the strategies in "draft-ietf-dnsop-refuse-any": returning
+         a single arbitrarily-selected RRset that matches the query
+         name rather than returning all of the matching RRsets.
+         Thanks to Tony Finch for the contribution. [RT #41615]
+       </para>
+      </listitem>
     </itemizedlist>
   </section>
 
index cb8e91ee5eb5fc2962579357528f0886e025e476..9156e82e0a55b1cb600ae263a1e571c9301a9ce1 100644 (file)
@@ -124,6 +124,7 @@ struct dns_view {
        isc_boolean_t                   auth_nxdomain;
        isc_boolean_t                   additionalfromcache;
        isc_boolean_t                   additionalfromauth;
+       isc_boolean_t                   minimal_any;
        isc_boolean_t                   minimalresponses;
        isc_boolean_t                   enablednssec;
        isc_boolean_t                   enablevalidation;
index 67dcf711250d8c773a6ec99db0b2f3aeb8c6661a..402c89b63bfed65f321c5893978614cf552b7664 100644 (file)
@@ -190,6 +190,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
        view->enablednssec = ISC_TRUE;
        view->enablevalidation = ISC_TRUE;
        view->acceptexpired = ISC_FALSE;
+       view->minimal_any = ISC_FALSE;
        view->minimalresponses = ISC_FALSE;
        view->transfer_format = dns_one_answer;
        view->cacheacl = NULL;
index 8e39a476eab40b5d628ceb0c31d7ac5bd9b21473..d23365ba27e0e896b9348232056f9d28225f7fbc 100644 (file)
@@ -1685,6 +1685,7 @@ view_clauses[] = {
        { "max-recursion-queries", &cfg_type_uint32, 0 },
        { "max-udp-size", &cfg_type_uint32, 0 },
        { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
+       { "minimal-any", &cfg_type_boolean, 0 },
        { "minimal-responses", &cfg_type_boolean, 0 },
        { "nta-recheck", &cfg_type_ttlval, 0 },
        { "nta-lifetime", &cfg_type_ttlval, 0 },