Knot DNSSEC key rollover, the secure way
The ZSK rollover is the easy one: Knot does it alone and nobody notices. The KSK rollover needs a human at a registrar web form, and Knot has an option that will happily finish the rollover without that human.
The short answer
Let Knot roll ZSKs automatically with pre-publication. For KSKs, set a finite lifetime, a submission section that checks the parent for the new DS, and a parent-delay equal to the parent's DS TTL. Never set a submission timeout. Update the DS at the registrar when CDS appears, and validate before and after.
On this page
What goes wrong
A zone has two kinds of keys. The zone signing key (ZSK) signs the records. The key signing key (KSK) signs the DNSKEY set, and the parent zone publishes a DS record that points to the KSK. That DS is the link resolvers follow.
A ZSK rollover touches only your zone. Knot publishes the new key, waits for caches to learn it, switches signing, then removes the old key. You can automate it completely.
A KSK rollover touches the parent. The new KSK is useless until the parent publishes a DS for it, and the old KSK must stay until every cache has the new DS. For most domains, only the registrar can change the DS. If the old KSK disappears before the new DS is live, every validating resolver returns SERVFAIL for the whole zone. That is a full outage, and it is self-inflicted.
Knot has an option that makes this outage easy. The timeout in a
submission section declares the DS "submitted" after a fixed time, whether
or not the parent changed anything.
What the docs say
The ZSK rollover is performed with Pre-publish method, KSK rollover uses Double-Signature scheme, as described in RFC 6781.
Source: Knot DNS 3.5 docs, DNSSEC key rollovers
After this time period (in seconds) the KSK submission is automatically considered successful, even if all the checks were negative or no parents are configured.
Source: Knot DNS 3.5 reference, submission timeout
The DS check tolerates unknown DS records at the parent, but it requires the previously known DS record to be removed; otherwise, the DS check remains negative.
Source: Knot DNS 3.5 docs, Automatic KSK and ZSK rollovers example
In practice, Dreg will not be a fixed time: instead, the end of Dreg will be signaled by the appearance of the DS record in the parent zone.
Source: RFC 7583, Section 3.3.1
The Knot docs explain every key state, but they leave the registrar step to
you: nothing in Knot can log in to a registrar. They also do not warn that
timeout removes the old KSK while the parent still points to it. RFC 7583
is clear that the registration delay is not a fixed time, which is exactly
why a fixed timeout is wrong.
The secure configuration
remote:
- id: validating_resolver
address: 198.51.100.53@53 # a resolver you trust, or the parent's servers
submission:
- id: parent_ds
parent: [ validating_resolver ] # Knot asks here for the new DS
check-interval: 1h
parent-delay: 1d # the parent's DS TTL: caches must forget the old DS
# no "timeout": the rollover waits for the real DS, however long it takes
policy:
- id: secure
algorithm: ecdsap256sha256
zsk-lifetime: 30d # automatic, pre-publish, no parent involved
ksk-lifetime: 365d # finite, so the KSK rollover path is exercised
propagation-delay: 1h # your slowest secondary plus signing time
dnskey-ttl: 3600
zone-max-ttl: 86400 # set explicitly; each step waits for it
cds-cdnskey-publish: rollover # CDS/CDNSKEY appear only while a DS is needed
ksk-submission: parent_ds
zone:
- domain: example.com
dnssec-signing: on
dnssec-policy: secureWhen the KSK rollover reaches submission, Knot logs KSK submission, waiting for confirmation and publishes CDS. Do the registrar step:
# 1. Read the DS for the new KSK (the tag is in the log and in the CDS record).
kdig @ns1.example.com example.com CDS +short
keymgr example.com ds <new-ksk-tag>
# 2. At the registrar: replace the old DS with the new one (digest type 2).
# Replace, do not add: Knot's DS check stays negative while the old DS is there.
# 3. Confirm the parent serves it, then let Knot's check pick it up.
kdig example.com DS @a.gtld-servers.net +norecurseIf you cannot give Knot a parent to query, leave parent unset and confirm
by hand after step 3 with knotc zone-ksk-submitted example.com.
Prove it
The test (secure-tests/knot-dnssec-key-rollover/run.sh) runs one Knot
3.5.4 instance with two zones. A stand-in com. zone plays the parent
registry and accepts DS changes only with a TSIG key named registrar.
example.com is the child, with lab lifetimes: KSK 40 seconds, ZSK 25
seconds, TTLs of 5 seconds. delv validates from a com. trust anchor.
Before: a submission timeout and nobody at the registrar
Policy with timeout: 8s in the submission section. The chain validates at
the start:
[20:24:22] registrar publishes DS for the first KSK 38820
[20:24:28] $ delv @127.0.0.1 -a anchor.conf +root=com www.example.com A
; fully validatedThe KSK rollover starts, waits 8 seconds, and declares success:
20:24:59 info: [example.com.] DNSSEC, KSK rollover started
20:25:06 notice: [example.com.] DNSSEC, KSK submission, waiting for confirmation
20:25:06 info: [example.com.] DNSSEC, key, tag 41202, algorithm ECDSAP256SHA256, KSK, public, ready, active+
20:25:14 notice: [example.com.] DNSSEC, KSK submission, confirmed
20:25:14 info: [example.com.] DNSSEC, next key action, KSK tag 38820, remove at 2026-09-24T20:25:14+0000The parent still points to the removed key, and the zone is bogus:
kdig @127.0.0.1 example.com DS +short
kdig @127.0.0.1 example.com DNSKEY +short | cut -c1-40
delv @127.0.0.1 -a anchor.conf +root=com www.example.com A38820 13 2 A964687067C91442284AF6EE0A2631635ADB8147C192F53C656F48A4B1DB0189
256 3 13 JDDOBRnUTOON0Y5DtoKiQq0qxtdKcEo
257 3 13 UIaWg3Q64zy+dJtL+6MwA8R+nUr3wuq
;; validating example.com/DNSKEY: no valid signature found (DS)
;; no valid RRSIG resolving 'example.com/DNSKEY/IN': 127.0.0.1#53
;; broken trust chain resolving 'www.example.com/A/IN': 127.0.0.1#53After: a parent DS check and the registrar step
Policy with parent: [parent], check-interval: 2s and parent-delay: 5s,
no timeout. The ZSK rolls first, with no parent involvement, and the chain
stays valid:
20:25:54 info: [example.com.] DNSSEC, ZSK rollover started
20:25:54 info: [example.com.] DNSSEC, next key action, ZSK tag 43496, replace at 2026-09-24T20:26:01+0000
20:26:01 info: [example.com.] DNSSEC, next key action, ZSK tag 23651, remove at 2026-09-24T20:26:08+0000
[20:26:03] $ delv @127.0.0.1 -a anchor.conf +root=com www.example.com A
; fully validatedThe KSK rollover reaches submission. Knot asks the parent and gets "negative" until the DS changes:
20:26:09 info: [example.com.] DNSSEC, KSK rollover started
20:26:16 notice: [example.com.] DNSSEC, KSK submission, waiting for confirmation
20:26:16 info: [example.com.] DNSSEC, key, tag 5435, algorithm ECDSAP256SHA256, KSK, public, ready, active+
20:26:20 info: [example.com.] DS check, outgoing, remote 127.0.0.1@53 TCP, KSK submission check: negative
20:26:22 info: [example.com.] DS check, outgoing, remote 127.0.0.1@53 TCP, KSK submission check: negativekdig @127.0.0.1 example.com CDS +short5435 13 2 6325EB84578DCCE1A32ACC71BA0A2E327E1CBD9176CDB922102EA1AB69415049The registrar step (in the lab, a TSIG-signed update to com.) replaces the
DS. The next check is positive, and only then does the old KSK get a removal
time, after parent-delay:
[20:26:22] REGISTRAR STEP: replace the DS at the parent with the DS for KSK 5435
20:26:24 info: [example.com.] DS check, outgoing, remote 127.0.0.1@53 TCP, KSK submission check: positive
20:26:24 notice: [example.com.] DNSSEC, KSK submission, confirmed
20:26:24 info: [example.com.] DNSSEC, next key action, KSK tag 56911, remove at 2026-09-24T20:26:34+0000
20:26:24 info: [example.com.] DNSSEC, key, tag 56911, algorithm ECDSAP256SHA256, KSK, public, active+
20:26:24 info: [example.com.] DNSSEC, key, tag 43496, algorithm ECDSAP256SHA256, public, active
20:26:24 info: [example.com.] DNSSEC, key, tag 5435, algorithm ECDSAP256SHA256, KSK, public, activeAfter the rollover, one KSK remains, it matches the parent, and the chain validates. (The second ZSK is the next ZSK rollover, already pre-published.)
kdig @127.0.0.1 example.com DS +short
kdig @127.0.0.1 example.com DNSKEY +short | cut -c1-40
delv @127.0.0.1 -a anchor.conf +root=com www.example.com A5435 13 2 6325EB84578DCCE1A32ACC71BA0A2E327E1CBD9176CDB922102EA1AB69415049
256 3 13 kDMrQG9HLB4L68+5zkcz2H7UY7X0AAZ
256 3 13 u2Bj5jYLNi9solkgYfnwoafLoscNIVE
257 3 13 TpH+jD4IAG7SPfcvrk+arJTX8wpSdb6
[20:26:39] $ delv @127.0.0.1 -a anchor.conf +root=com www.example.com A
; fully validatedMistakes people make
The timeout that finishes without you
timeout in a submission section looks like a safety net. It is the
opposite. After it expires, Knot retires the old KSK whether or not the
parent changed. If the registrar step was forgotten, the zone goes bogus,
as the test shows. Leave timeout unset (the default, 0, means infinity).
Adding the new DS but never removing the old one
Some registrar forms add a DS record next to the existing one. Knot's check requires the previously known DS to be gone, so the check stays negative and the rollover never finishes. Replace the DS; do not append.
Setting parent-delay to zero in production
When the parent starts serving the new DS, caches still hold the old DS for
up to its TTL. If the old KSK leaves before that, those caches fail to
validate. Set parent-delay to at least the parent's DS TTL. Check it with
kdig example.com DS @<parent server> +norecurse.
Pointing the DS check at a caching forwarder
A plain caching forwarder can keep answering with the old DS until its
cached copy expires, so the check lags behind the parent. Point parent at
the parent's authoritative servers, or at a validating resolver you control
and can flush.
Changing TTLs in the middle of a rollover
Knot plans each rollover step from dnskey-ttl, zone-max-ttl and
propagation-delay. Its reference warns: "Ensure all DNSKEYs with updated
TTL are propagated before any subsequent DNSKEY rollover starts." Change TTLs
only when no rollover runs, then wait at least one old TTL.
Checklist
- Set
ksk-lifetimeandzsk-lifetimeexplicitly in the policy. - Configure a
submissionsection withparentset to the parent's servers or a validating resolver. - Set
parent-delayto at least the parent's DS TTL. - Remove any
timeoutfrom everysubmissionsection. - Alert on the log line
KSK submission, waiting for confirmation. - At the registrar, replace the old DS with the new one; do not keep both.
- Confirm the new DS with
kdig DSagainst every parent server before walking away. - Run
delvagainst the real root trust anchor before, during and after each KSK rollover. - Check
knotc zone-statusfor the next signing time after each step.
Knot handles every rollover step it can see. The one step it cannot see, the registrar form, is the only one that ever takes a zone down, so give it a check, not a timer.
H2-CPQE
Learn it on a live range
DNSSEC with Knot, in Edge and Post-Quantum Networking: a real host in your browser, and every objective checked on the machine.
Start freeThe Dome
Want it run for you?
The Dome puts post-quantum TLS, a WAF that blocks, signed DNS and a zero-trust mesh in front of your application. Tell us what you run.
See the Dome