]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add stale-cache-enable option and disable serve-stable by default
authorOndřej Surý <ondrej@isc.org>
Tue, 21 Jul 2020 08:38:55 +0000 (10:38 +0200)
committerMatthijs Mekking <matthijs@isc.org>
Wed, 5 Aug 2020 07:09:16 +0000 (09:09 +0200)
The current serve-stale implementation in BIND 9 stores all received
records in the cache for a max-stale-ttl interval (default 12 hours).

This allows DNS operators to turn the serve-stale answers in an event of
large authoritative DNS outage.  The caching of the stale answers needs
to be enabled before the outage happens or the feature would be
otherwise useless.

The negative consequence of the default setting is the inevitable
cache-bloat that happens for every and each DNS operator running named.

In this MR, a new configuration option `stale-cache-enable` is
introduced that allows the operators to selectively enable or disable
the serve-stale feature of BIND 9 based on their decision.

The newly introduced option has been disabled by default,
e.g. serve-stale is disabled in the default configuration and has to be
enabled if required.

(cherry picked from commit ce53db34d601b107d268889893e3f40693bd8d35)

16 files changed:
bin/named/config.c
bin/named/named.conf.rst
bin/named/server.c
bin/tests/system/serve-stale/managed-keys.bind.jnl [new file with mode: 0644]
bin/tests/system/serve-stale/ns1/named1.conf.in
bin/tests/system/serve-stale/ns1/named2.conf.in
bin/tests/system/serve-stale/ns3/named.conf.in
bin/tests/system/serve-stale/ns4/named.conf.in
bin/tests/system/serve-stale/setup.sh
bin/tests/system/serve-stale/tests.sh
doc/arm/reference.rst
doc/man/named.conf.5in
doc/misc/options
doc/misc/options.active
doc/misc/options.grammar.rst
lib/isccfg/namedconf.c

index 878dcfda5086c94509516bf6fc963b06c504fb49..8685c9543cc72821aa47dbef5e01130a07a9d591 100644 (file)
@@ -195,6 +195,7 @@ options {\n\
 #      sortlist <none>\n\
        stale-answer-enable false;\n\
        stale-answer-ttl 1; /* 1 second */\n\
+       stale-cache-enable false;\n\
        synth-from-dnssec no;\n\
 #      topology <none>\n\
        transfer-format many-answers;\n\
index 45a2cc76d1a03fc21b59aa2fc6b9e79f933d5764..b4d07a32ca3be18ed82cafa6aa08692085bd30e7 100644 (file)
@@ -412,6 +412,7 @@ OPTIONS
        stacksize ( default | unlimited | sizeval );
        stale-answer-enable boolean;
        stale-answer-ttl duration;
+       stale-cache-enable boolean;
        startup-notify-rate integer;
        statistics-file quoted_string;
        synth-from-dnssec boolean;
@@ -785,6 +786,7 @@ VIEW
        sortlist { address_match_element; ... };
        stale-answer-enable boolean;
        stale-answer-ttl duration;
+       stale-cache-enable boolean;
        synth-from-dnssec boolean;
        transfer-format ( many-answers | one-answer );
        transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [
index 7e3aabe71f1404226bc7b4ed80fb0fe49b0dc1de..c0b29fd2060939757f4f2f536d6787ec151b791b 100644 (file)
@@ -3892,7 +3892,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
        uint32_t max_cache_size_percent = 0;
        size_t max_adb_size;
        uint32_t lame_ttl, fail_ttl;
-       uint32_t max_stale_ttl;
+       uint32_t max_stale_ttl = 0;
        dns_tsig_keyring_t *ring = NULL;
        dns_view_t *pview = NULL; /* Production view */
        isc_mem_t *cmctx = NULL, *hmctx = NULL;
@@ -4355,9 +4355,14 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
        view->synthfromdnssec = cfg_obj_asboolean(obj);
 
        obj = NULL;
-       result = named_config_get(maps, "max-stale-ttl", &obj);
+       result = named_config_get(maps, "stale-cache-enable", &obj);
        INSIST(result == ISC_R_SUCCESS);
-       max_stale_ttl = ISC_MAX(cfg_obj_asduration(obj), 1);
+       if (cfg_obj_asboolean(obj)) {
+               obj = NULL;
+               result = named_config_get(maps, "max-stale-ttl", &obj);
+               INSIST(result == ISC_R_SUCCESS);
+               max_stale_ttl = ISC_MAX(cfg_obj_asduration(obj), 1);
+       }
 
        obj = NULL;
        result = named_config_get(maps, "stale-answer-enable", &obj);
diff --git a/bin/tests/system/serve-stale/managed-keys.bind.jnl b/bin/tests/system/serve-stale/managed-keys.bind.jnl
new file mode 100644 (file)
index 0000000..6d114b6
Binary files /dev/null and b/bin/tests/system/serve-stale/managed-keys.bind.jnl differ
index c29bcd7a44f48cd6f4523a7468df47eaa7f80094..a16f28a55e43cf25972ce9c837a2acf4f8b66208 100644 (file)
@@ -30,6 +30,7 @@ options {
        max-stale-ttl 3600;
        stale-answer-ttl 2;
        stale-answer-enable yes;
+       stale-cache-enable yes;
        servfail-ttl 0;
 };
 
index a41f07b140ff4cbbbc64d6d1aec8098da88458fe..1dda6398ec6215633a8869930af40c08e4b7b00f 100644 (file)
@@ -30,6 +30,7 @@ options {
        max-stale-ttl 20;
        stale-answer-ttl 3;
        stale-answer-enable yes;
+       stale-cache-enable yes;
        servfail-ttl 0;
 };
 
index ac8083037290416cc38088a0518dd12b69290b3e..d5943a9a0233501bbf63a068f95c51063963e17c 100644 (file)
@@ -28,7 +28,7 @@ options {
        listen-on-v6 { none; };
        recursion yes;
        dump-file "named_dump3.db";
-       // This configuration has no serve-stale options set.
+       stale-cache-enable yes;
 };
 
 zone "." {
index cd255b06d441d6c2ce89dc2a73895627588f6cbc..9c502ba0e41c1b5e226206ee3dbb923dde1f3f45 100644 (file)
@@ -29,6 +29,7 @@ options {
        recursion yes;
        dump-file "named_dump4.db";
        stale-answer-enable no;
+       stale-cache-enable yes;
 };
 
 zone "." {
index 79d7238cf96d682bde40d73f72cca5cf652703ef..6b1e260531f87bf9f14de506fc3ae7399d301cf5 100644 (file)
@@ -17,3 +17,4 @@ $SHELL clean.sh
 copy_setports ns1/named1.conf.in ns1/named.conf
 copy_setports ns3/named.conf.in ns3/named.conf
 copy_setports ns4/named.conf.in ns4/named.conf
+copy_setports ns5/named.conf.in ns5/named.conf
index c1271f5640735559f01ad2d2c50d167d0d6b593b..b7d3a9977932d1452d2a93e9bf90b784fa09a27b 100755 (executable)
@@ -862,7 +862,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status+ret))
 
 #
-# Now test server with serve-stale disabled.
+# Now test server with serve-stale answers disabled.
 #
 echo_i "test server with serve-stale disabled"
 
@@ -876,7 +876,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status+ret))
 
 n=$((n+1))
-echo_i "prime cache longttl.example (serve-stale disabled) ($n)"
+echo_i "prime cache longttl.example (serve-stale answers disabled) ($n)"
 ret=0
 $DIG -p ${PORT} @10.53.0.4 longttl.example TXT > dig.out.test$n
 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
@@ -885,7 +885,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status+ret))
 
 n=$((n+1))
-echo_i "prime cache data.example (serve-stale disabled) ($n)"
+echo_i "prime cache data.example (serve-stale answers disabled) ($n)"
 ret=0
 $DIG -p ${PORT} @10.53.0.4 data.example TXT > dig.out.test$n
 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
@@ -895,7 +895,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status+ret))
 
 n=$((n+1))
-echo_i "prime cache othertype.example (serve-stale disabled) ($n)"
+echo_i "prime cache othertype.example (serve-stale answers disabled) ($n)"
 ret=0
 $DIG -p ${PORT} @10.53.0.4 othertype.example CAA > dig.out.test$n
 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
@@ -905,7 +905,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status+ret))
 
 n=$((n+1))
-echo_i "prime cache nodata.example (serve-stale disabled) ($n)"
+echo_i "prime cache nodata.example (serve-stale answers disabled) ($n)"
 ret=0
 $DIG -p ${PORT} @10.53.0.4 nodata.example TXT > dig.out.test$n
 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
@@ -915,7 +915,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status+ret))
 
 n=$((n+1))
-echo_i "prime cache nxdomain.example (serve-stale disabled) ($n)"
+echo_i "prime cache nxdomain.example (serve-stale answers disabled) ($n)"
 ret=0
 $DIG -p ${PORT} @10.53.0.4 nxdomain.example TXT > dig.out.test$n
 grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
@@ -925,7 +925,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status+ret))
 
 n=$((n+1))
-echo_i "verify prime cache statistics (serve-stale disabled) ($n)"
+echo_i "verify prime cache statistics (serve-stale answers disabled) ($n)"
 ret=0
 rm -f ns4/named.stats
 $RNDCCMD 10.53.0.4 stats > /dev/null 2>&1
@@ -973,7 +973,7 @@ waitfile dig.out.test$((n+3))
 waitfile dig.out.test$((n+4))
 
 n=$((n+1))
-echo_i "check fail of data.example (serve-stale disabled) ($n)"
+echo_i "check fail of data.example (serve-stale answers disabled) ($n)"
 ret=0
 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
@@ -981,7 +981,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status+ret))
 
 n=$((n+1))
-echo_i "check fail of othertype.example (serve-stale disabled) ($n)"
+echo_i "check fail of othertype.example (serve-stale answers disabled) ($n)"
 ret=0
 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
@@ -989,7 +989,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status+ret))
 
 n=$((n+1))
-echo_i "check fail of nodata.example (serve-stale disabled) ($n)"
+echo_i "check fail of nodata.example (serve-stale answers disabled) ($n)"
 ret=0
 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
@@ -997,7 +997,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status+ret))
 
 n=$((n+1))
-echo_i "check fail of nxdomain.example (serve-stale disabled) ($n)"
+echo_i "check fail of nxdomain.example (serve-stale answers disabled) ($n)"
 ret=0
 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
@@ -1005,7 +1005,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status+ret))
 
 n=$((n+1))
-echo_i "verify stale cache statistics (serve-stale disabled) ($n)"
+echo_i "verify stale cache statistics (serve-stale answers disabled) ($n)"
 ret=0
 rm -f ns4/named.stats
 $RNDCCMD 10.53.0.4 stats > /dev/null 2>&1
@@ -1025,7 +1025,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
 
 # Dump the cache.
 n=$((n+1))
-echo_i "dump the cache (serve-stale disabled) ($n)"
+echo_i "dump the cache (serve-stale answers disabled) ($n)"
 ret=0
 $RNDCCMD 10.53.0.4 dumpdb -cache > rndc.out.test$n 2>&1 || ret=1
 done=0
@@ -1050,7 +1050,7 @@ LASTWEEK=`TZ=UTC perl -e 'my $now = time();
         printf("%04d%02d%02d%02d%02d%02d", $y+1900, $mo+1, $d, $h, $m, $s);'`
 
 n=$((n+1))
-echo_i "mock the cache date to $LASTWEEK (serve-stale disabled) ($n)"
+echo_i "mock the cache date to $LASTWEEK (serve-stale answers disabled) ($n)"
 ret=0
 sed -E "s/DATE [0-9]{14}/DATE $LASTWEEK/g" ns4/named_dump4.db > ns4/named_dumpdb4.db.out || ret=1
 cp ns4/named_dumpdb4.db.out ns4/named_dumpdb4.db
@@ -1061,7 +1061,7 @@ echo_i "start ns4"
 $PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} serve-stale ns4
 
 n=$((n+1))
-echo_i "verify ancient cache statistics (serve-stale disabled) ($n)"
+echo_i "verify ancient cache statistics (serve-stale answers disabled) ($n)"
 ret=0
 rm -f ns4/named.stats
 $RNDCCMD 10.53.0.4 stats #> /dev/null 2>&1
index d7434a44131c7fab5798c2eb1a3d1777e94b7239..84f7e3a18d17adc377b61eb7a32cd5213105a16f 100644 (file)
@@ -1820,9 +1820,9 @@ Boolean Options
    The default is ``yes``.
 
 ``stale-answer-enable``
-   If ``yes``, enable the returning of "stale" cached answers when the name servers
-   for a zone are not answering. The default is not to return stale
-   answers.
+   If ``yes``, enable the returning of "stale" cached answers when the name
+   servers for a zone are not answering and the ``stale-cache-enable`` option is
+   also enabled. The default is not to return stale answers.
 
    Stale answers can also be enabled or disabled at runtime via
    ``rndc serve-stale on`` or ``rndc serve-stale off``; these override
@@ -1836,6 +1836,9 @@ Boolean Options
    Information about stale answers is logged under the ``serve-stale``
    log category.
 
+``stale-cache-enable``
+   If ``yes``, enable the retaining of "stale" cached answers.  Default ``no``.
+
 ``nocookie-udp-size``
    This sets the maximum size of UDP responses that are sent to queries
    without a valid server COOKIE. A value below 128 is silently
@@ -3251,15 +3254,20 @@ Tuning
    (such as NS and glue AAAA/A records) in the resolution process.
 
 ``max-stale-ttl``
-   If stale answers are enabled, ``max-stale-ttl`` sets the maximum time
+   If retaining stale RRsets in cache is enabled, and returning of stale cached
+   answers is also enabled, ``max-stale-ttl`` sets the maximum time
    for which the server retains records past their normal expiry to
    return them as stale records, when the servers for those records are
    not reachable. The default is 12 hours. The minimum allowed is 1
    second; a value of 0 is updated silently to 1 second.
 
-   For stale answers to be returned, they must be enabled, either in the
-   configuration file using ``stale-answer-enable`` or via
-   ``rndc serve-stale on``.
+   For stale answers to be returned, the retaining of them in cache must be
+   enabled via the configuration option ``stale-cache-enable``, and returning
+   cached answers must be enabled, either in the configuration file using the
+   ``stale-answer-enable`` option or by calling ``rndc serve-stale on``.
+
+   When ``stale-cache-enable`` is set to ``no``, setting the ``max-stale-ttl``
+   has no effect, the value of ``max-cache-ttl`` will be ``0`` in such case.
 
 ``resolver-nonbackoff-tries``
    This specifies how many retries occur before exponential backoff kicks in. The
index 4ddf4e0176cc0718196f161bf1f8f5391809af0b..7392fecca83a908ff4d9e93bd8eb3308fb843a4e 100644 (file)
@@ -465,6 +465,7 @@ options {
       stacksize ( default | unlimited | sizeval );
       stale\-answer\-enable boolean;
       stale\-answer\-ttl duration;
+      stale\-cache\-enable boolean;
       startup\-notify\-rate integer;
       statistics\-file quoted_string;
       synth\-from\-dnssec boolean;
@@ -862,6 +863,7 @@ view string [ class ] {
       sortlist { address_match_element; ... };
       stale\-answer\-enable boolean;
       stale\-answer\-ttl duration;
+      stale\-cache\-enable boolean;
       synth\-from\-dnssec boolean;
       transfer\-format ( many\-answers | one\-answer );
       transfer\-source ( ipv4_address | * ) [ port ( integer | * ) ] [
index 0845abe17321164455e2091f5c6d83bf04ba3bd5..77fed614106dd6844276aab227d5d5b288652649 100644 (file)
@@ -366,6 +366,7 @@ options {
         stacksize ( default | unlimited | <sizeval> );
         stale-answer-enable <boolean>;
         stale-answer-ttl <duration>;
+        stale-cache-enable <boolean>;
         startup-notify-rate <integer>;
         statistics-file <quoted_string>;
         statistics-interval <integer>; // ancient
@@ -742,6 +743,7 @@ view <string> [ <class> ] {
         sortlist { <address_match_element>; ... };
         stale-answer-enable <boolean>;
         stale-answer-ttl <duration>;
+        stale-cache-enable <boolean>;
         suppress-initial-notify <boolean>; // not yet implemented
         synth-from-dnssec <boolean>;
         topology { <address_match_element>; ... }; // ancient
index d347c31e0aa2fd0c17c54a525d728160b92a9e15..500fcd81388d8b55b92b88f028a75df5fce0a9c2 100644 (file)
@@ -330,6 +330,7 @@ options {
         stacksize ( default | unlimited | <sizeval> );
         stale-answer-enable <boolean>;
         stale-answer-ttl <duration>;
+        stale-cache-enable <boolean>;
         startup-notify-rate <integer>;
         statistics-file <quoted_string>;
         synth-from-dnssec <boolean>;
@@ -671,6 +672,7 @@ view <string> [ <class> ] {
         sortlist { <address_match_element>; ... };
         stale-answer-enable <boolean>;
         stale-answer-ttl <duration>;
+        stale-cache-enable <boolean>;
         synth-from-dnssec <boolean>;
         transfer-format ( many-answers | one-answer );
         transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [
index baaa6110df615894a1b955415937322b1781999b..b0a9ab532cbe9a0cb2f071e6826338750d7e95c4 100644 (file)
        stacksize ( default | unlimited | <sizeval> );
        stale-answer-enable <boolean>;
        stale-answer-ttl <duration>;
+       stale-cache-enable <boolean>;
        startup-notify-rate <integer>;
        statistics-file <quoted_string>;
        synth-from-dnssec <boolean>;
index 516be5cc2bd358c064aea3a0be17e0f24241d5bd..83090832d22b38bad6a9f1ebda6c2646fe2a640a 100644 (file)
@@ -2042,6 +2042,7 @@ static cfg_clausedef_t view_clauses[] = {
        { "sortlist", &cfg_type_bracketed_aml, 0 },
        { "stale-answer-enable", &cfg_type_boolean, 0 },
        { "stale-answer-ttl", &cfg_type_duration, 0 },
+       { "stale-cache-enable", &cfg_type_boolean, 0 },
        { "suppress-initial-notify", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
        { "synth-from-dnssec", &cfg_type_boolean, 0 },
        { "topology", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_ANCIENT },