Jitter signatures times when adding dynamic records.

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).
This commit is contained in:
Witold Kręcicki
2019-11-06 13:31:25 +01:00
committed by Matthijs Mekking
parent 7c7f5884e5
commit 6b2fd40269
3 changed files with 62 additions and 14 deletions
+21 -1
View 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;
+38 -10
View 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);
}
+3 -3
View 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,