Knot has become much more mature and solid since I last looked at it almost five years ago – time flies!

It sports a new configuration file format (YAML) which is optionally backed by an LMDB database, a key manager which takes care of ZSK/KSK key rollovers and timings, and lots of changes which make the server and its utilities appear much more solid and quite a bit snappier. It’s worth scrolling through Knot’s changelog to see how the program has evolved.

A project I’ll likely soon be asked to start working on has a requirement for Knot because a front-end bit of DNS software requires a DNSSEC signer and the implementation specifically calls for the Czech software.

Simultaneously, the same company will soon embark on a project to rejuvenate an OpenDNSSEC installation, and I’ve been asked to assist with that. My gut feeling is that the current signer software is seeing very little love, and since the requirement of using HSMs for storing private DNSSEC key material has been dropped (does anybody need a half a dozen high-end HSM?), I recommend using Knot as a signer for two reasons:

  1. it will be the same software used in the first department; this will simplify and hopefully ease knowledge transfer
  2. DS-PUSH, which I’ll explain in a moment.

The authoritative Knot DNSSEC signer optionally publishes CDS/CDNSKEY records in a signed zone. (We’ve previously discussed CDS and CDNSKEY records and what they’re used for here.)

remote:
   - id: knotmaster
     address: 127.0.0.1
     key: km_updater

submission:
   - id: ds_checker
     check-interval: 10s
     parent: knotmaster

policy:
   - id: rsa00
     algorithm: RSASHA256
     ksk-size: 2048
     zsk-size: 1024
     cds-cdnskey-publish: rollover
     ksk-submission: ds_checker

zone:
   - domain: f8.example
     dnssec-signing: on
     dnssec-policy: rsa00

These records can be used to signal to the parent zone that a DS record has changed in the child zone. During a KSK roll, Knot can attempt to consume (i.e. verify if a record exists in the parent zone) a DS record before actually activating a KSK to ensure that a key roll is performed correctly; this is configured by the (IMO confusingly-named submission stanza).

info: [f8.example.] DS check, outgoing, remote 127.0.0.1@53, KSK submission attempt: negative

We could use the log message to trigger a DS upload or do it manually using knsupdate; note the k:

#!/bin/sh

p=example
z=f8.example
cds=$(dig +short @127.0.0.1 $z CDS)

knsupdate <<END
server 127.0.0.1
zone ${p}.
update delete ${z}. DS
update add ${z}. 60 DS ${cds}
send
END

As soon as the DS is seen in the parent zone, Knot logs the following messages:

info: [f8.example.] DS check, outgoing, remote 127.0.0.1@53, KSK submission attempt: positive
notice: [f8.example.] DNSSEC, KSK submission, confirmed

The operator ensures the DS is uploaded to the parent and then, using knotc zone-ksk-submitted $zone signals Knot that the roll is to be completed whereupon the CDS/CDNSKEY records in the child are removed.

automation: ds-push

Knot can help me eliminate a lot of lovingly hand-written code from the above-mentioned “legacy” project by automatically submitting DS records. That’s what ds-push accomplishes: automatic upload of DS records to parent zones. This environment consists of a completely separate DNSSEC-signed root zone, and all zones must have their DS records uploaded to the root zone and be subsequently signed. Seeing we control the whole infrastructure, that is relatively easy to manage.

policy:
   - id: rsa00
     ...
     cds-cdnskey-publish: rollover
     ksk-submission: ds_checker
     ds-push: knotmaster

Knot is capable of doing this by itself. In the above configuration, I add a ds-push setting to the signing policy; this instructs Knot to push DS records to the specified remote (a remote configures a particular server). In this specific case, as the parent zone is signed and served by the same server, the remote specifies the Knot master server proper.

When a zone is signed, Knot publishes CDS records and uploads the hashes as DS records to the parent’s server via a dynamic DNS update

info: [f7.example.] DS push, outgoing, remote 127.0.0.1@53, success
info: [f7.example.] DS check, outgoing, remote 127.0.0.1@53, KSK submission attempt: positive
notice: [f7.example.] DNSSEC, KSK submission, confirmed

I’ve had dozens of KSK rollovers done in the course of the last 24 hours (one every five minutes), and this is working very well, with the exception that Knot appends the new DS only where it should replace; I reported this as an issue and it was solved 20 hours later – long live Open Source maintainers!

With the exception of the root’s KSK which for which I’ll likely use CDS signalling as the trust anchor has to be copied to all manner of places, this automatic handling of DS uploads is very promising.

adding zones

Knot supports adding zones to a running server, using the knotc utility:

#!/bin/sh
z=f8.example

knotc <<EOF
conf-begin
conf-set zone[$z]
conf-set zone[$z].file $z.zone
conf-set zone[$z].acl jp01
conf-set zone[$z].dnssec-signing on
conf-set zone[$z].dnssec-policy rsa00
conf-set zone[$z].zonefile-sync -1
conf-set zone[$z].zonefile-load difference
conf-set zone[$z].journal-content changes
conf-set zone[$z].serial-policy increment
conf-commit
EOF

I still have to learn how to best manage the configuration: knot.conf (the YAML) can be backed by an LMDB database, and that’s where the above zone is added to. Using knotc I can read the runtime configuration and all sorts of other information from the running server, but I’ll want to persist that.

dnstap

Knot has for some releases provided the possibility for logging via dnstap, and we discussed this here some time ago.

Further reading: