-
chevron_right
DNSSEC signing with an offline KSK
pubsub.slavino.sk / jpmens.net · Wednesday, 21 September, 2022 - 22:00 · 5 minutes
The level of complexity caused by KSK/ZSK split in DNSSEC isn’t necessary for most purposes; you can in fact just have one key for a zone and sign everything with it such. co.uk. does this , and I also make frequent use of Combined Signing Key (or Single Signing Key).
However, the KSK/ZSK split has one advantage: it allows us to keep the KSK offline and only bring it out occasionally to sign the DNSKEY RRset. This key can be kept stable (i.e. it need to be changed frequently or at all) and thus the interaction with the parent (DS submission) be kept at a minimum.
Jaromir Talir held a presentation about offline KSK with Knot DNS , and from the terminology he used in 2019 I made this diagram a few years ago to help me better understand the flow of keys.
The idea is that the KSK (depicted on the left) is managed completely offline. Only public keys are carried around – on floppy disks or USB keys, say, and as such there is an extremely low risk of the KSK being compromised.
The ZSK and the zone proper are maintained on the right, online and/or on a hidden primary. Since the ZSK can easily be replaced there is little risk of compromise, and the zone data is public anyway.
Once created, the ZSK (or ZSKs – plural) are copied to the KSK machine for signing. The KSK signer uses the KSK to sign the DNSKEY RRset and the resulting RRset and its signatures (RRSIG) are transported back to the zone signer on the right. This data is now public: the DNSKEY RRset contains the public keys for the zone.
The zone is now signed (on the right) with the ZSK only, so this signs all of the RRsets in the zone, and as a last step we enrich the newly-signed zone with the public DNSKEY of the KSK and its signatures, and this zone (named
example.com.final
in the diagram) we then load and serve.
The diagram shows “key requests” being passed left and right. These could be signed (PGP?) containers carrying public key material, but for our purposes simple files containing the public DNSKEY records suffice.
In the example which follows, the offline KSK will be managed with tools from the ldns toolchain, and the zone signer with tools from BIND and optionally from ldns . Why? Just to introduce diversity.
creating the keys
We begin by preparing our environment. Everything in the directory
left
contains files which we will have on the offline KSK machine; conversely, the directory
right
contains files on our actual zone signer.
% mkdir left right
% touch left/KSK.data #this file will contain public data
% cd right/
right% dnssec-keygen -a13 example.com #generate ZSK
Generating key pair.
Kexample.com.+013+54147
right% ln -s Kexample.com.+013+54147.key ZSK.key
We copy the public
ZSK.key
to the
left
. In the following script, I have to replace
$INCLUDE.*$
by the actual public ZSK DNSKEY RR because
ldns-read-zone
and friends don’t understand
$INCLUDE
.
% cd left/
left% ldns-keygen -a13 -k example.com #generate KSK
Kexample.com.+013+11238
left% cat example.com
$TTL 3600
@ SOA unused.invalid. jp.invalid. 1 3H 1H 1W 1H
NS unused.invalid.
;$INCLUDE"../zone/ZSK.key";This is a ZONE-SIGNING key, keyid 54147, for example.com.
example.com. IN DNSKEY 256 3 13 ah+p9L1ydOMAWsHTW9sLokRDrA1by6TV6ZPLKPDhkowEMAN7o36Vs1Bt db+obk6h22D548XWTWV6cWEkbNYHPQ==
left% cat Kexample.com.+013+11238.ds
example.com. IN DS 11238 13 2 2d0d834fe6aea4c80ec3bcbf5af753653c9d9ea6dc997ea86e90c2615edef19f
Note the DS record which we will later submit to the parent. This is public data, so we can safely copy it to the right for further submission.
On the left, the content of the zone doesn’t matter; I’ve used
invalid.
to underline the fact. We will now sign that zone with the KSK, and I set the signature validity to a date I’ll recognize in the final zone. The only records from this signed zone we are interested in are the DNSKEY and RRSIG over DNSKEY.
left% ldns-signzone -e 20221224 -o example.com example.com Kexample.com.+013+11238
#now grab the KSK DNSKEY record and its RRSIG
left% ldns-read-zone example.com.signed |
awk '($4 =="DNSKEY"&&$5== 257)||($4=="RRSIG"&&$5=="DNSKEY"){ print }' | tee KSK.data
example.com. 3600 IN DNSKEY 257 3 13 cMW3t5/jWcESqrzNgNjksnfUZdS4TtqO1gOae0cBRxgopoT/FNIa5GATNQAg64TJw3tgECVOq1beXpbJGSjG7Q== ;{id = 11238 (ksk), size = 256b}
example.com. 3600 IN RRSIG DNSKEY 13 2 3600 20221224000000 20220922073938 11238 example.com. 35J+toX0FyIyXRTNpamM6UVyivLFV1deUSWrJl+3DCVH2feolbDP45i/myLDnnywAS4NzQIZqjdkZQMTyVSxfg==
left% wc -l KSK.data
2 KSK.data
The file
KSK.data
contains the public key and signature which we transfer (floppy disk, remember?) back to the
right
.
signing the zone
Back on the
right
we have the zone, the ZSK, and the public KSK in the file
KSK.data
, so we can now sign this:
right% ./bsig.sh
*** sign the zone;set SOA serial to epoch
example.com.signed
*** remove dsset file as it contains ZSK only
*** replace RRSIG over DNSKEY created by ZSK with that created by KSK
*** verify signed zone using ldns-verify-zone
Zone is verified and complete
*** verify signed zone using dnssec-verify
Loading zone 'example.com' from file 'example.com.signed'
Verifying the zone using the following algorithms: ECDSAP256SHA256.
Zone fully signed:
Algorithm: ECDSAP256SHA256: KSKs: 1 active, 0 stand-by, 0 revoked
ZSKs: 1 active, 0 stand-by, 0 revoked
*** verify signed zone using validns
records found: 17
skipped dups: 0
record sets found: 10
unique names found: 3
delegations found: 0
nsec3 records: 0
not authoritative names, not counting delegation points:
0
validation errors: 0
signatures verified: 8
time taken: 0.003s
The
b
in
bsig.sh
is for signing with the
BIND
utilities, and there’s an
lsig.sh
which uses
ldns
for signing.
Both scripts work in a similar way: they first sign the zone using only our ZSK (BIND’s smart signing finds the key by itself, with ldns I have to specify it). Then they remove the RRSIG over DNSKEY which was created by the ZSK (we don’t need that; our DNSKEY RRset is signed by the KSK), and add the public DNSKEY of the KSK and its RRSIG, both obtained from
left
. Finally, we use three distinct tools to verify the validity of the zone.
The signed zone file is the one we (re-)load on our (hidden) primary server.
finally
As the diagram above suggests, there’s no reason why you couldn’t add
complexity
security by adding a bunch of HSMs here and there.
And if you don’t like using floppy disks to transport the public keys from
right
to
left
and back, but want to make life difficult for intruders, a serial cable and the likes of
UUCP
or
Kermit
might be employed. :-)
Značky: #Network