I’ve seen several questions in recent weeks on mailing lists and on OARC’s chat server about migrating signed zones to KnotDNS, in particular from BIND. I’ve done a few of these migrations in the last couple of years, so I thought it might be useful to write up the general process I used. Perhaps this will be useful to someone.

In a couple of cases I was moving zones from extremely old setups using ancient shell scripts for signing, with basically no key rotation happening at all. In some cases these were zones that had been signed since before the root zone got signed, with no updates to the process, so using incredibly basic tooling. This means that one of the basic assumptions of these instructions is that the key meta-data are way out of date.

Another basic assumption of these instructions is that there’s a desire to avoid starting an immediate key roll when the zones are brought online within Knot. While starting a key roll right away isn’t likely to cause any major issues, it’s generally safest to keep the number of changes you make in any one step to a minimum, and immediately rolling both keys upon import definitely violates that principle.

The final assumption of this post is that you already have a working knowledge of Knot configuration. This isn’t a general tutorial on setting up Knot, just the specific steps necessary for importing signed zones. As such I will gloss over some configuration details that you’re expected to already have in place.

Identify Your Key Data

If you have files for more than two keys present you’ll need to identify which keys are relevant. The easiest way to do this is with dig, using the +rrcomments argument to get the production Key IDs from the primary name server.

% dig +short +rrcomments IN DNSKEY example.com @ns1.example.com
256 3 7 AwEAAbuZt8a668svYzNuY7M6gyV56UZXHTBlhyq8lIqX9HQ12zU9UmDo7Fj4/86oKcFcuCJBq0gIJNhuu11kNGLnWSOFJZG+C/eq/RCe6dzbL/ec MbTJl+lfeYkBgAidNtL6x0mjGxb5qhrJV6m54sQUS1q2tRrbLtJc1ys1 BgUmGDNb ; ZSK; alg = NSEC3RSASHA1 ; key id = 12345
257 3 7 AwEAAZcxOcM4vJhZEAIVEySQzu7uCYDkAJiKZz2QxrVfr08m+3IHtkm0nsZj2AZaPcI6rc7YiZcoaYcA0ZCaUejrcFz+W+T8KAbk64Ari5HPYRlx UT2BiYLSV4lmtAb+6UdREB3s0ywk3j1jae4/WUAYxURKXTZ/3Ap8B80q 4YENc3QBcEbN7su3l8iT3dpLRg0Z/UqfRXDMJtUYyN2reFpba7UJ1GC3 2zXrUt5LHWFFVlMcP7JlwBeZXFvVlNSbkVyWPexiSWMbKSLuGmYJT+4T BCSpEonBfv+/Ym1VDvq6FpFZktbQlnIJa/q35K7t58Eazc8Da2ZtgE1j 6iP2JBsoZs8= ; KSK; alg = NSEC3RSASHA1 ; key id = 67890

You’ll be looking for matching public/private key pairs wherever your current name server stores its key files. With some platforms’ default configurations this may be in a directory containing all of your other zone data, or it may be in a special-purpose directory for keys from all of your zones. The file names for the above keys will look something like this:

Kexample.com.+007+12345.key
Kexample.com.+007+12345.private
Kexample.com.+007+67890.key
Kexample.com.+007+67890.private

Copy these key files to somewhere you can safely edit them (the copies) without affecting your currently running name server.

Add the Zone to Knot

Copy the zone to the location for zone files on your Knot server. This may be /var/lib/knot/zones/, depending on your platform and configuration. If there are any BIND-specific directives in your zone file you’ll need to remove them; this means things like the $GENERATE or $INCLUDE statements. If any of these are present in the zone you’ll need to re-work the zone contents to make them unnecessary.

Configure Knot to load the zone with DNSSEC disabled. You’ll need to do this because you can’t import the zone keys into Knot’s key manager unless it already knows about the zone. If you have an existing Knot configuration you may already have a useful zone template for unsigned zones, but if not you’ll need to create a zone template similar to the one below.

template:
  - id: nodnssec
    storage: "/var/lib/knot/zones"
    file: "%s"
    dnssec-signing: off

zone:
  - domain: example.com
    template: nodnssec

Once the zone is configured, reload Knot so that it loads the zone. Be sure to check the Knot logs for any errors.

% sudo knotc reload

Prep and Import Key Files

In your copies of the original key files you’ll likely need to modify some meta-data. Assuming the keys haven’t been rotated recently, the date meta-data in the key files are what will trigger Knot to immediately start rolling keys. You’ll want to change those dates in order to avoid triggering the key roll. What I did for all of mine was to set the dates to the day I was doing the key import. Your public key files will start with comments that look like this:

; This is a zone-signing key, keyid 12345, for example.com.
; Created: 20141015213926 (Wed Oct 15 21:39:26 2014)
; Publish: 20141015213926 (Wed Oct 15 21:39:26 2014)
; Activate: 20141015213956 (Wed Oct 15 21:39:56 2014)

And your private key file will end with comments that look like this:

Created: 20141015213926
Publish: 20141015213926
Activate: 20141015213956

Change all of these dates—in all four key files—to something recent. I chose to use midnight UTC on the day I was making the change. If I did this today these would look like this:

; This is a zone-signing key, keyid 12345, for example.com.
; Created: 20230104000000 (Wed Jan 04 00:00:00 2023)
; Publish: 20230104000000 (Wed Jan 04 00:00:00 2023)
; Activate: 20230104000000 (Wed Jan 04 00:00:00 2023)

---

Created: 20230104000000
Publish: 20230104000000
Activate: 20230104000000

Once the date meta-data are updated, import the keys into the Knot key manager. You can import the key files with a simple shell one-liner like this:

% for file in *.private;
   do sudo -u knot keymgr example.com import-bind $file;
done

Important

Make certain that all of the key files are readable by the Knot user (e.g. chmod go+r *.{private,key}) or you will get the extremely cryptic error: not exists error from keymgr. This is confusing, and apparently not easily fixed.

Now check that the keys were imported correctly, both are active, and that Knot hasn’t initiated a key roll.

% sudo keymgr example.com list

You should only see the keys you imported listed. The publish and active fields for both keys should be a unix epoch value that matches the dates you set in the key meta-data. If the other state fields are shown at all (ready and everything else to the right), they should be all zeros. More recent versions of Knot appear to not show these states if they are zero.

Activate Signing

At this point you can change the zone configuration to enable DNSSEC signing using the keys you just imported. You’ll need to define a dnssec policy that matches the keys you imported. If the policy and the keys don’t match, Knot will generate new keys that do match the policy and initiate a key roll.

policy:
  - id: nsec3rsa
    algorithm: rsasha1-nsec3-sha1
    ksk-size: 2048
    zsk-size: 1024

zone:
  - domain: example.com
    policy: nsec3rsa

Reload Knot and confirm in the log files and by querying the server that the keys you expect are the ones being used to sign the zone. Knot’s kdig doesn’t have an equivalent to dig‘s +rrcomments argument which will show you key IDs, but you should be able to tell from the log output, and by eye-balling the public key data from kdig output to see that Knot is still only serving the two keys you expect.

% kdig +short +dnssec IN DNSKEY example.com @localhost
256 3 7 AwEAAbuZt8a668svYzNuY7M6gyV56UZXHTBlhyq8lIqX9HQ12zU9UmDo7Fj4/ 86oKcFcuCJBq0gIJNhuu11kNGLnWSOFJZG+C/eq/RCe6dzbL/ec MbTJl+ lfeYkBgAidNtL6x0mjGxb5qhrJV6m54sQUS1q2tRrbLtJc1ys1 BgUmGDNb
257 3 7 AwEAAZcxOcM4vJhZEAIVEySQzu7uCYDkAJiKZz2QxrVfr08m+ 3IHtkm0nsZj2AZaPcI6rc7YiZcoaYcA0ZCaUejrcFz+W+T8KAbk64Ari5HPYRlx UT2BiYLSV4lmtAb+6UdREB3s0ywk3j1jae4/WUAYxURKXTZ/3Ap8B80q 4YENc3QBcEbN7su3l8iT3dpLRg0Z/          UqfRXDMJtUYyN2reFpba7UJ1GC3 2zXrUt5LHWFFVlMcP7JlwBeZXFvVlNSbkVyWPexiSWMbKSLuGmYJT+4T BCSpEonBfv+/ Ym1VDvq6FpFZktbQlnIJa/q35K7t58Eazc8Da2ZtgE1j 6iP2JBsoZs8=
DNSKEY 7 2 1800 20230101000000 20230107000000 12345 example.com. ZLH5zS39E3+b/fMef3fTrksMportgK50D0JyZd+2BG31 /9JCfFG1pGtUesdH6MPZynUxaZMiynYjv2BT5sUa93vZ dflfNXwpgELm+ghOLLRtUQKRLkU+4vIrG0j0iHByOGZn vuqf5GoGzW/Bpl7PQXQ0R1iHSTl2ywmX7NJP2tU=

That’s It!

You should now be able to switch your name server infrastructure to transfer the zone from your Knot server instead of the old server. Once the zone has propagated to your secondary name servers, it’s time to update the zone policy in Knot to change the key algorithm or key sizes (especially if you’re using an insanely outdated algorithm as with the zone in this example).

Let me know if this was useful to you, or if there are ways I can improve the instructions!

Edit

I am reliably informed that there are a couple of command line options to kdig that can provide DNSSEC keytag information. I still haven’t worked kdig into my routine, mostly continuing to rely on dig, and so I’m not well acquainted with some of its nuance. The suggestions are to use either +multiline or +nocrypto; for these purposes, +nocrypto looks like the most concise result, which will get you something like this:

% kdig +nocrypto +short IN DNSKEY example.com @localhost
256 3 7 [id = 12345]
257 3 7 [id = 67890]

#100DaysToOffload article 1 of 100