]> 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 15:30:50 +0000 (16:30 +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).

Manually edits: resolve conflicts, replace isc_random_uniform
with isc_random_jitter.

(cherry picked from commit 6b2fd40269a69044ecc13e063fca3eae04be36d1)

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

index 7c9afc24e83d35b688c8b00a5d2e2584b3cc6285..c48c0fd863425975ba96d1cd966a07d070498a12 100644 (file)
@@ -21,6 +21,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>
@@ -1380,6 +1381,27 @@ 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);
+               uint32_t jitter;
+               isc_random_get(&jitter);
+
+               if (sigvalidityinterval < 7200U) {
+                       expiryinterval = 1200;
+               } else if (expiryinterval > sigvalidityinterval) {
+                       expiryinterval = sigvalidityinterval;
+               } else {
+                       expiryinterval = sigvalidityinterval - expiryinterval;
+               }
+               jitter %= 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,
@@ -1433,7 +1455,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);
 
                /*
                 * Do we look at the KSK flag on the DNSKEY to determining which
index a326d01604aa29a27809e6bba2a08d38df6d5c42..e8cff77588cee4e280e23a41aff051cc7a5311c6 100644 (file)
@@ -6542,8 +6542,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;
@@ -6591,21 +6591,37 @@ 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) {
-               isc_random_get(&jitter);
+               uint32_t normaljitter, fulljitter;
+               isc_random_get(&normaljitter);
+               isc_random_get(&fulljitter);
                if (sigvalidityinterval > 7200U) {
-                       jitter %= 3600;
+                       normaljitter %= 3600;
+                       fulljitter %= expiryinterval;
                } else {
-                       jitter %= 1200;
+                       normaljitter %= 1200;
+                       fulljitter %= 1200;
                }
-               expire = soaexpire - jitter - 1;
+               expire = soaexpire - normaljitter - 1;
+               fullexpire = soaexpire - fulljitter - 1;
        } else {
-               expire = soaexpire - 1;
+               expire = fullexpire = soaexpire - 1;
        }
        stop = now + 5;
 
@@ -6645,9 +6661,16 @@ 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, covers, zonediff.diff,
                                  zone_keys, nkeys, zone->mctx, inception,
-                                 expire, check_ksk, keyset_kskonly);
+                                 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",
@@ -7540,7 +7563,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;
@@ -7612,6 +7635,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
@@ -7621,7 +7650,7 @@ zone_nsec3chain(dns_zone_t *zone) {
        if (sigvalidityinterval >= 3600U) {
                isc_random_get(&jitter);
                if (sigvalidityinterval > 7200U) {
-                       jitter %= 3600;
+                       jitter %= expiryinterval;
                } else {
                        jitter %= 1200;
                }