mirror of
https://github.com/coredns/coredns.git
synced 2025-10-28 08:44:17 -04:00
sign: add expiration jitter (#3588)
* add expiration jitter Signed-off-by: Miek Gieben <miek@miek.nl> * sign: add expiration jitter This PR adds a expiration jitter to spread out zone re-signing even more. The max is 5 extra days added when creating the signer for a specific zone. Also make the duration* constants private to clean up the godoc for this plugin. Signed-off-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
@@ -32,7 +32,7 @@ it do key or algorithm rollovers - it just signs.
|
|||||||
Both these dates are only checked on the SOA's signature(s).
|
Both these dates are only checked on the SOA's signature(s).
|
||||||
|
|
||||||
* Create RRSIGs that have an inception of -3 hours (minus a jitter between 0 and 18 hours)
|
* Create RRSIGs that have an inception of -3 hours (minus a jitter between 0 and 18 hours)
|
||||||
and a expiration of +32 days for every given DNSKEY.
|
and a expiration of +32 (plus a jitter between 0 and 5 days) days for every given DNSKEY.
|
||||||
|
|
||||||
* Add NSEC records for all names in the zone. The TTL for these is the negative cache TTL from the
|
* Add NSEC records for all names in the zone. The TTL for these is the negative cache TTL from the
|
||||||
SOA record.
|
SOA record.
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func setup(c *caddy.Controller) error {
|
|||||||
c.OnStartup(sign.OnStartup)
|
c.OnStartup(sign.OnStartup)
|
||||||
c.OnStartup(func() error {
|
c.OnStartup(func() error {
|
||||||
for _, signer := range sign.signers {
|
for _, signer := range sign.signers {
|
||||||
go signer.refresh(DurationRefreshHours)
|
go signer.refresh(durationRefreshHours)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@@ -66,7 +66,8 @@ func parse(c *caddy.Controller) (*Sign, error) {
|
|||||||
signers[i] = &Signer{
|
signers[i] = &Signer{
|
||||||
dbfile: dbfile,
|
dbfile: dbfile,
|
||||||
origin: plugin.Host(origins[i]).Normalize(),
|
origin: plugin.Host(origins[i]).Normalize(),
|
||||||
jitter: time.Duration(float32(DurationJitter) * rand.Float32()),
|
jitterIncep: time.Duration(float32(durationInceptionJitter) * rand.Float32()),
|
||||||
|
jitterExpir: time.Duration(float32(durationExpirationDayJitter) * rand.Float32()),
|
||||||
directory: "/var/lib/coredns",
|
directory: "/var/lib/coredns",
|
||||||
stop: make(chan struct{}),
|
stop: make(chan struct{}),
|
||||||
signedfile: fmt.Sprintf("db.%ssigned", origins[i]), // origins[i] is a fqdn, so it ends with a dot, hence %ssigned.
|
signedfile: fmt.Sprintf("db.%ssigned", origins[i]), // origins[i] is a fqdn, so it ends with a dot, hence %ssigned.
|
||||||
|
|||||||
@@ -26,12 +26,13 @@ func (s *Sign) OnStartup() error {
|
|||||||
|
|
||||||
// Various duration constants for signing of the zones.
|
// Various duration constants for signing of the zones.
|
||||||
const (
|
const (
|
||||||
DurationExpireDays = 7 * 24 * time.Hour // max time allowed before expiration
|
durationExpireDays = 7 * 24 * time.Hour // max time allowed before expiration
|
||||||
DurationResignDays = 6 * 24 * time.Hour // if the last sign happenend this long ago, sign again
|
durationResignDays = 6 * 24 * time.Hour // if the last sign happenend this long ago, sign again
|
||||||
DurationSignatureExpireDays = 32 * 24 * time.Hour // sign for 32 days
|
durationSignatureExpireDays = 32 * 24 * time.Hour // sign for 32 days
|
||||||
DurationRefreshHours = 5 * time.Hour // check zones every 5 hours
|
durationRefreshHours = 5 * time.Hour // check zones every 5 hours
|
||||||
DurationJitter = -18 * time.Hour // default max jitter
|
durationInceptionJitter = -18 * time.Hour // default max jitter for the inception
|
||||||
DurationSignatureInceptionHours = -3 * time.Hour // -(2+1) hours, be sure to catch daylight saving time and such, jitter is subtracted
|
durationExpirationDayJitter = 5 * 24 * time.Hour // default max jitter for the expiration
|
||||||
|
durationSignatureInceptionHours = -3 * time.Hour // -(2+1) hours, be sure to catch daylight saving time and such, jitter is subtracted
|
||||||
)
|
)
|
||||||
|
|
||||||
const timeFmt = "2006-01-02T15:04:05.000Z07:00"
|
const timeFmt = "2006-01-02T15:04:05.000Z07:00"
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ type Signer struct {
|
|||||||
origin string
|
origin string
|
||||||
dbfile string
|
dbfile string
|
||||||
directory string
|
directory string
|
||||||
jitter time.Duration
|
jitterIncep time.Duration
|
||||||
|
jitterExpir time.Duration
|
||||||
|
|
||||||
signedfile string
|
signedfile string
|
||||||
stop chan struct{}
|
stop chan struct{}
|
||||||
@@ -42,7 +43,7 @@ func (s *Signer) Sign(now time.Time) (*file.Zone, error) {
|
|||||||
|
|
||||||
mttl := z.Apex.SOA.Minttl
|
mttl := z.Apex.SOA.Minttl
|
||||||
ttl := z.Apex.SOA.Header().Ttl
|
ttl := z.Apex.SOA.Header().Ttl
|
||||||
inception, expiration := lifetime(now, s.jitter)
|
inception, expiration := lifetime(now, s.jitterIncep, s.jitterExpir)
|
||||||
z.Apex.SOA.Serial = uint32(now.Unix())
|
z.Apex.SOA.Serial = uint32(now.Unix())
|
||||||
|
|
||||||
for _, pair := range s.keys {
|
for _, pair := range s.keys {
|
||||||
@@ -143,8 +144,8 @@ func resign(rd io.Reader, now time.Time) (why error) {
|
|||||||
}
|
}
|
||||||
incep, _ := time.Parse("20060102150405", dns.TimeToString(x.Inception))
|
incep, _ := time.Parse("20060102150405", dns.TimeToString(x.Inception))
|
||||||
// If too long ago, resign.
|
// If too long ago, resign.
|
||||||
if now.Sub(incep) >= 0 && now.Sub(incep) > DurationResignDays {
|
if now.Sub(incep) >= 0 && now.Sub(incep) > durationResignDays {
|
||||||
return fmt.Errorf("inception %q was more than: %s ago from %s: %s", incep.Format(timeFmt), DurationResignDays, now.Format(timeFmt), now.Sub(incep))
|
return fmt.Errorf("inception %q was more than: %s ago from %s: %s", incep.Format(timeFmt), durationResignDays, now.Format(timeFmt), now.Sub(incep))
|
||||||
}
|
}
|
||||||
// Inception hasn't even start yet.
|
// Inception hasn't even start yet.
|
||||||
if now.Sub(incep) < 0 {
|
if now.Sub(incep) < 0 {
|
||||||
@@ -152,8 +153,8 @@ func resign(rd io.Reader, now time.Time) (why error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expire, _ := time.Parse("20060102150405", dns.TimeToString(x.Expiration))
|
expire, _ := time.Parse("20060102150405", dns.TimeToString(x.Expiration))
|
||||||
if expire.Sub(now) < DurationExpireDays {
|
if expire.Sub(now) < durationExpireDays {
|
||||||
return fmt.Errorf("expiration %q is less than: %s away from %s: %s", expire.Format(timeFmt), DurationExpireDays, now.Format(timeFmt), expire.Sub(now))
|
return fmt.Errorf("expiration %q is less than: %s away from %s: %s", expire.Format(timeFmt), durationExpireDays, now.Format(timeFmt), expire.Sub(now))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
@@ -173,7 +174,7 @@ func signAndLog(s *Signer, why error) {
|
|||||||
z, err := s.Sign(now)
|
z, err := s.Sign(now)
|
||||||
log.Infof("Signing %q because %s", s.origin, why)
|
log.Infof("Signing %q because %s", s.origin, why)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warningf("Error signing %q with key tags %q in %s: %s, next: %s", s.origin, keyTag(s.keys), time.Since(now), err, now.Add(DurationRefreshHours).Format(timeFmt))
|
log.Warningf("Error signing %q with key tags %q in %s: %s, next: %s", s.origin, keyTag(s.keys), time.Since(now), err, now.Add(durationRefreshHours).Format(timeFmt))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +182,7 @@ func signAndLog(s *Signer, why error) {
|
|||||||
log.Warningf("Error signing %q: failed to move zone file into place: %s", s.origin, err)
|
log.Warningf("Error signing %q: failed to move zone file into place: %s", s.origin, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Infof("Successfully signed zone %q in %q with key tags %q and %d SOA serial, elapsed %f, next: %s", s.origin, filepath.Join(s.directory, s.signedfile), keyTag(s.keys), z.Apex.SOA.Serial, time.Since(now).Seconds(), now.Add(DurationRefreshHours).Format(timeFmt))
|
log.Infof("Successfully signed zone %q in %q with key tags %q and %d SOA serial, elapsed %f, next: %s", s.origin, filepath.Join(s.directory, s.signedfile), keyTag(s.keys), z.Apex.SOA.Serial, time.Since(now).Seconds(), now.Add(durationRefreshHours).Format(timeFmt))
|
||||||
}
|
}
|
||||||
|
|
||||||
// refresh checks every val if some zones need to be resigned.
|
// refresh checks every val if some zones need to be resigned.
|
||||||
@@ -202,8 +203,8 @@ func (s *Signer) refresh(val time.Duration) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func lifetime(now time.Time, jitter time.Duration) (uint32, uint32) {
|
func lifetime(now time.Time, jitterInception, jitterExpiration time.Duration) (uint32, uint32) {
|
||||||
incep := uint32(now.Add(DurationSignatureInceptionHours).Add(jitter).Unix())
|
incep := uint32(now.Add(durationSignatureInceptionHours).Add(jitterInception).Unix())
|
||||||
expir := uint32(now.Add(DurationSignatureExpireDays).Unix())
|
expir := uint32(now.Add(durationSignatureExpireDays).Add(jitterExpiration).Unix())
|
||||||
return incep, expir
|
return incep, expir
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user