]> 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>
Tue, 4 Aug 2020 08:50:31 +0000 (10:50 +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.

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 f073bcd328a6c4cf5ec1a17b86059ad915246077..de45c0a7524091fb76e4773fea0e787e88cf879a 100644 (file)
@@ -196,6 +196,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 2b982d580afcbfe8f84143dea42bb16ae2c0bd8e..f66c485ad6740d81f1050b9d46bc729607ac3b8c 100644 (file)
@@ -401,6 +401,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 81cf4b592f917e2d77f2f15885d72f6b2249b95d..82179cdeb83244300123d06ce7a2d993ab35e892 100644 (file)
@@ -3895,7 +3895,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;
@@ -4358,9 +4358,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 04fe0ce3bd1851e50b87becba32e166e647194e7..6586849d8531bba325a0115ad7ba8ae959ba8324 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 6361f591a6269ef4ad700831a123cbba15fb3b19..06fae5369c2c61d90e62e41d66d80fc1ecacb746 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 451cfd47ae0e86fe29687bb159ede96120928a57..d76b348151369e6de5c71669c37fd213d8777085 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 c2b05e1ec33fbe80f9de251507fa80bfb657fe13..392ec1d6f513ecbeb0081d8129dc6be7825f9e50 100644 (file)
@@ -29,6 +29,7 @@ options {
        recursion yes;
        dump-file "named_dump4.db";
        stale-answer-enable no;
+       stale-cache-enable yes;
 };
 
 zone "." {
index 963278e976140df51d8c583f11c0c3ce6f22a6d7..868c6c876cd4b2dec4f6292bbd54a104ec0afe27 100644 (file)
@@ -16,3 +16,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 7c9de93bdda6319541eb71086d0c841bb92b2681..96037328d42fce9011b39a8d096fab64bd9f88dd 100755 (executable)
@@ -861,7 +861,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"
 
@@ -875,7 +875,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
@@ -884,7 +884,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
@@ -894,7 +894,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
@@ -904,7 +904,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
@@ -914,7 +914,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
@@ -924,7 +924,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
@@ -972,7 +972,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
@@ -980,7 +980,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
@@ -988,7 +988,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
@@ -996,7 +996,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
@@ -1004,7 +1004,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
@@ -1024,7 +1024,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
@@ -1049,7 +1049,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
@@ -1060,7 +1060,7 @@ echo_i "start ns4"
 start_server --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 82795ca4f54543985e99044a3792b4739544c163..6a782a831f094965b9629f03e68a6cadf1fcbe58 100644 (file)
@@ -1815,9 +1815,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
@@ -1831,6 +1831,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
@@ -3246,15 +3249,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 0e77255d9bd563661d38781eb162ee4a21a6dd8c..85f5b6d22a90a93b09fdc5297e83516dc835a0be 100644 (file)
@@ -464,6 +464,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;
@@ -876,6 +877,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 0a648e8a461c6b47a1092646bef7eb2185b8af62..7640b8d4c84b1c775e7d5a5d9be6e4384b6b74c7 100644 (file)
@@ -365,6 +365,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
@@ -747,6 +748,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 018548edcc79c603211f16591e3f47c9a459e54e..3deea19bb50a3e3aa76634b548d73c1820924744 100644 (file)
@@ -329,6 +329,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>;
@@ -676,6 +677,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 034302cc290e880bfb09ebb831635966556db359..dffce2f4a676b4fbd1bfda9a6d95e357736795ac 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 2e93cb3faac9301594b8a94f67a378538e88098a..9084e63db515124e1e823dcdd4a231de2126767f 100644 (file)
@@ -2045,6 +2045,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 },