]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Jitter signatures times when adding dynamic records.
authorWitold Kręcicki <wpk@isc.org>
Wed, 9 Oct 2019 15:38:44 +0000 (17:38 +0200)
committerMatthijs Mekking <matthijs@isc.org>
Wed, 6 Nov 2019 12:31:25 +0000 (13:31 +0100)
When doing regular signing expiry time is jittered to make sure
that the re-signing times are not clumped together. This expands
this behaviour to expiry times of dynamically added records.

When incrementally re-signing a zone use the full jitter range if
the server appears to have been offline for greater than 5 minutes
otherwise use a small jitter range of 3600 seconds.  This will stop
the signatures becoming more clustered if the server has been off
line for a significant period of time (> 5 minutes).

lib/dns/update.c
lib/dns/zone.c
lib/ns/update.c

index 48aa23b30d81e7df197ca33bb8adbd668f18f271..25827d4b5437252557c385603d1cffd8b7e0ad24 100644 (file)
@@ -19,6 +19,7 @@
 #include <isc/netaddr.h>
 #include <isc/platform.h>
 #include <isc/print.h>
+#include <isc/random.h>
 #include <isc/serial.h>
 #include <isc/stats.h>
 #include <isc/stdtime.h>
@@ -1389,6 +1390,25 @@ struct dns_update_state {
               sign_nsec, update_nsec3, process_nsec3, sign_nsec3 } state;
 };
 
+static uint32_t
+dns__jitter_expire(dns_zone_t *zone, uint32_t sigvalidityinterval) {
+       /* Spread out signatures over time */
+       if (sigvalidityinterval >= 3600U) {
+               uint32_t expiryinterval = dns_zone_getsigresigninginterval(zone);
+
+               if (sigvalidityinterval < 7200U) {
+                       expiryinterval = 1200;
+               } else if (expiryinterval > sigvalidityinterval) {
+                       expiryinterval = sigvalidityinterval;
+               } else {
+                       expiryinterval = sigvalidityinterval - expiryinterval;
+               }
+               uint32_t jitter = isc_random_uniform(expiryinterval);
+               sigvalidityinterval -= jitter;
+       }
+       return (sigvalidityinterval);
+}
+
 isc_result_t
 dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
                         dns_dbversion_t *oldver, dns_dbversion_t *newver,
@@ -1440,7 +1460,7 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
 
                isc_stdtime_get(&now);
                state->inception = now - 3600; /* Allow for some clock skew. */
-               state->expire = now + sigvalidityinterval;
+               state->expire = now + dns__jitter_expire(zone, sigvalidityinterval);
                state->keyexpire = dns_zone_getkeyvalidityinterval(zone);
                if (state->keyexpire == 0) {
                        state->keyexpire = state->expire;
index cea7c31ec4edf039d06cc40c642f640f00281c78..6d5417955774be7ce5f4f9c49cd4faa9eb733650 100644 (file)
@@ -6613,8 +6613,8 @@ zone_resigninc(dns_zone_t *zone) {
        dst_key_t *zone_keys[DNS_MAXZONEKEYS];
        bool check_ksk, keyset_kskonly = false;
        isc_result_t result;
-       isc_stdtime_t now, inception, soaexpire, expire, stop;
-       uint32_t jitter, sigvalidityinterval;
+       isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop;
+       uint32_t sigvalidityinterval, expiryinterval;
        unsigned int i;
        unsigned int nkeys = 0;
        unsigned int resign;
@@ -6662,20 +6662,34 @@ zone_resigninc(dns_zone_t *zone) {
        sigvalidityinterval = zone->sigvalidityinterval;
        inception = now - 3600; /* Allow for clock skew. */
        soaexpire = now + sigvalidityinterval;
+       expiryinterval = dns_zone_getsigresigninginterval(zone);
+       if (expiryinterval > sigvalidityinterval) {
+               expiryinterval = sigvalidityinterval;
+       } else {
+               expiryinterval = sigvalidityinterval - expiryinterval;
+       }
+
        /*
         * Spread out signatures over time if they happen to be
         * clumped.  We don't do this for each add_sigs() call as
-        * we still want some clustering to occur.
+        * we still want some clustering to occur.  In normal operations
+        * the records should be re-signed as they fall due and they should
+        * already be spread out.  However if the server is off for a
+        * period we need to ensure that the clusters don't become
+        * synchronised by using the full jitter range.
         */
        if (sigvalidityinterval >= 3600U) {
+               uint32_t normaljitter, fulljitter;
                if (sigvalidityinterval > 7200U) {
-                       jitter = isc_random_uniform(3600);
+                       normaljitter = isc_random_uniform(3600);
+                       fulljitter = isc_random_uniform(expiryinterval);
                } else {
-                       jitter = isc_random_uniform(1200);
+                       normaljitter = fulljitter = isc_random_uniform(1200);
                }
-               expire = soaexpire - jitter - 1;
+               expire = soaexpire - normaljitter - 1;
+               fullexpire = soaexpire - fulljitter - 1;
        } else {
-               expire = soaexpire - 1;
+               expire = fullexpire = soaexpire - 1;
        }
        stop = now + 5;
 
@@ -6715,9 +6729,17 @@ zone_resigninc(dns_zone_t *zone) {
                        break;
                }
 
+               /*
+                * If re-signing is over 5 minutes late use 'fullexpire'
+                * to redistribute the signature over the complete
+                * re-signing window, otherwise only add a small amount
+                * of jitter.
+                */
                result = add_sigs(db, version, name, zone, covers,
                                  zonediff.diff, zone_keys, nkeys, zone->mctx,
-                                 inception, expire, check_ksk, keyset_kskonly);
+                                 inception,
+                                 resign > (now - 300) ? expire : fullexpire,
+                                 check_ksk, keyset_kskonly);
                if (result != ISC_R_SUCCESS) {
                        dns_zone_log(zone, ISC_LOG_ERROR,
                                     "zone_resigninc:add_sigs -> %s",
@@ -7677,7 +7699,7 @@ zone_nsec3chain(dns_zone_t *zone) {
        bool first;
        isc_result_t result;
        isc_stdtime_t now, inception, soaexpire, expire;
-       uint32_t jitter, sigvalidityinterval;
+       uint32_t jitter, sigvalidityinterval, expiryinterval;
        unsigned int i;
        unsigned int nkeys = 0;
        uint32_t nodes;
@@ -7749,6 +7771,12 @@ zone_nsec3chain(dns_zone_t *zone) {
        sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
        inception = now - 3600; /* Allow for clock skew. */
        soaexpire = now + sigvalidityinterval;
+       expiryinterval = dns_zone_getsigresigninginterval(zone);
+       if (expiryinterval > sigvalidityinterval) {
+               expiryinterval = sigvalidityinterval;
+       } else {
+               expiryinterval = sigvalidityinterval - expiryinterval;
+       }
 
        /*
         * Spread out signatures over time if they happen to be
@@ -7757,7 +7785,7 @@ zone_nsec3chain(dns_zone_t *zone) {
         */
        if (sigvalidityinterval >= 3600U) {
                if (sigvalidityinterval > 7200U) {
-                       jitter = isc_random_uniform(3600);
+                       jitter = isc_random_uniform(expiryinterval);
                } else {
                        jitter = isc_random_uniform(1200);
                }
index 5cc5c1728d26f2cb5c2d690547c3af1c189236de..3baf428bd883c27c3369efe0c39810d6d773c1c2 100644 (file)
@@ -3181,14 +3181,14 @@ update_action(isc_task_t *task, isc_event_t *event) {
                         CHECK(dns_nsec3param_deletechains(db, ver, zone,
                                                           true, &diff));
                } else if (has_dnskey && isdnssec(db, ver, privatetype)) {
-                       uint32_t interval;
                        dns_update_log_t log;
+                       uint32_t interval = dns_zone_getsigvalidityinterval(zone);
 
-                       interval = dns_zone_getsigvalidityinterval(zone);
                        log.func = update_log_cb;
                        log.arg = client;
                        result = dns_update_signatures(&log, zone, db, oldver,
-                                                      ver, &diff, interval);
+                                                      ver, &diff,
+                                                      interval);
 
                        if (result != ISC_R_SUCCESS) {
                                update_log(client, zone,