DNSSEC signing your domain with BIND 9.16

Update December 2022: added “inline-signing yes;” to the zone statement as BIND 9.16.33, 9.18.7 and newer requires an explicit statement for zones without a configured ‘allow-update’ or ‘update-policy’ (see KB).

BIND 9.16 has improved DNSSEC support to the point where it can (finally) be called simple to use. This is excellent news for DNS administrators because it means there are now several options (viable alternatives being Knot DNS or PowerDNS) which make DNSSEC simple to deploy.

Six years ago we wrote a blog post about BIND 9.9 and its new in-line signing support. This article got a lot of views but at some point we had to put a warning message on the blog post stating vaguely that we would not recommend the method described anymore. The main reason was that DNSSEC with BIND 9.9 still contained many manual steps which could not be configured in named.conf. Especially key roll-overs caused headaches for administrators. If you cannot upgrade to BIND 9.16 the old blog post might still be useful. But in this case, we recommend to omit key roll-overs altogether.

However, now that we have BIND 9.16, you can just make some configuration changes to named.conf and it’s all done. Now let’s take a closer look on how you can enable DNSSEC for your domain name.

OS Setup

We used Debian 10 (aka buster) which comes with BIND 9.11 at the time of writing. We used the BIND9 packages provided by ISC, who offer BIND 9.16 in the “BIND 9 Stable” repository. Please head over to ISC Packages for BIND 9 for instructions on how to use the ISC packages directly.

Once you have added the ISC BIND 9 Stable repository we install bind9, bind9 utils and the bind documentation:

apt-get install bind9 bind9-dnsutils bind9-doc

You have now a running bind9 instance. You can check its running state with systemctl:

systemctl status bind9

Test Zone Setup

Debian uses /etc/bind as the default configuration directory and expects you to add zone statements to named.conf.local. We will start with a simple zone statement for einbeispiel.ch:

zone einbeispiel.ch. {
   type master;
   file "/etc/bind/zones/db.einbeispiel.ch";

The einbeispiel.ch zone content is taken from a previous blog post about zone time value recommendations and adapted for the domain name einbeispiel.ch.

Debian expects your dynamically updated zone (and journal) files in /var/lib/bind (See /etc/apparmor.d/usr.sbin.named). That’s why we create a symbolic link from /etc/bind/zones to /var/lib/bind/ and place the db.einbeispiel.ch file in there:

ln -s /var/lib/bind /etc/bind/zones

Reload the configuration with rndc reconfig and test if you can query the einbeispiel.ch zone:

dig @::1 einbeispiel.ch

DNSSEC Sign Your Zone

ISC has an excellent DNSSEC Guide. This blog post does not cover most DNSSEC configuration settings. We strongly recommend readers to at least skim over the “Signing” chapter for more details.

We will now adapt the zone statement to sign the zone with the default DNSSEC policy:

zone einbeispiel.ch. {
   type master;
   dnssec-policy default;
   inline-signing yes;
   file "/etc/bind/zones/db.einbeispiel.ch";

Again, reload the configuration after you are done and check that your zone is signed:

dig @::1 einbeispiel.ch +dnssec

That’s it. BIND has created a so-called combined signing key (CSK) using the DNSSEC algorithm ecdsap256sha256 (algorithm number 13) (Key directory /var/cache/bind/). The key is never changed in the default policy and NSEC is used for Proof of Non-Existence. For more details about the default signing policy please check the BIND dnssec-policy Grammar in the BIND documentation or the output of the following file /usr/share/doc/bind9-doc/misc/dnssec-policy.default.conf.

If you want to tweak some parameters of the default signing policy copy the above file content to named.conf.local, change the policy name to something else e.g. test and reference this policy in the zone statement.

Add Public Key to Parent Zone

Your zone is now DNSSEC signed but it is still treated as unsigned by recursive resolvers. The reason is that the parent zone indicates that your zone is not signed. You have to add the DS or DNSKEY record to the parent zone so that recursive resolvers have a path to validate your zone records.

SWITCH, the registry for .ch and .li, supports automated DNSSEC provisioning: We poll all child zones for the presence of a CDS record and if such a record is present for three consecutive days and has not changed, we accept it and bootstrap DNSSEC automatically for you. See Automated DNSSEC Provisioning for more details.

If your registrar or parent zone does not poll for CDS or CDNSKEY records you have to manually add your public key to the parent zone whenever you change your keys. This typically involves logging into the registrars web interface and provide the DNSKEY details.

The just signed einbeispiel.ch zone does not publish a CDS/CDNSKEY record just yet. However, as soon as its safe to publish these records, BIND will do so automatically (See also bind user mailing list for an answer about the expected delay). So in about 1 day, the CDS record should be published in your einbeispiel.ch zone. The following command should then have an output like this:

dig @::1 einbeispiel.ch CDS

; <<>> DiG 9.16.9-Debian <<>> @::1 einbeispiel.ch CDS
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63251
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

; EDNS: version: 0, flags:; udp: 1232
; COOKIE: a9547708f4c9666d010000005fc4f0be861bf22a24c61238 (good)
;einbeispiel.ch. IN CDS

einbeispiel.ch. 60 IN CDS 27064 13 2 48CF11D9C0E58172B47BD6DD2374EA18B67303108C9CE612C22DBA23 35E52E84

You can check the parent zone if it already contains the DS record:

dig @a.nic.ch einbeispiel.ch DS

The nic.ch web whois interface also indicates if the zone is signed or you can also use the CDS Status Check on nic.ch.

Zone Monitoring

We recommend that you monitor your zone. The previous blog post already covered this. Our recommendations have not changed since then and we summarized the main four points below for you. For more details please refer to the previous blog post.

  1. keep your system time on the server synchronised with a time server
  2. monitor the zone’s SOA serial number across all authoritative name servers
  3. test that DNSSEC signing is still enabled and that validation works
  4. test that DNSSEC signatures are renewed automatically

For 3. and 4. we can recommend the check_dnssec_expiry Icinga / Nagios Plugin by Mario Rimann.

2 thoughts on “DNSSEC signing your domain with BIND 9.16”

  1. Is there a difference or advantage in using the ISC repo instead of the official buster-backport?

    1. It looks like the ISC repo is slightly more up to date (9.16.9 vs 9.16.8). However, I have not compared the packages specifically.

Comments are closed.

%d bloggers like this: