Knot DNS: One Tame and Sane Authoritative DNS Server
How to install and minimally configure Knotto act as your home lab's local domain master and slave servers.
If you were a regular viewer of the originalSaturday Night Live era, youwill remember the Festrunks, two lewd but naïve Czech brothers who wereself-described "wild and crazy guys!" For me, Gyorg and Yortuk(plus having my binomial handed to me by tests designed by a brilliant Czechprofessor at the local university's high-school mathematics contests) werethe extent of my knowledge of the Czech Republic.
I recently discovered something else Czech, and it's not wild and crazyat all, but quite tame and sane, open-source and easy to configure.Knot DNSis an authoritative DNS server written in 2011 bythe Czech CZ.NIC organization. They wrote and continue to maintain it toserve their national top-level domain (TLD) as well as to prevent furtherextension of a worldwide BIND9 software monoculture across all TLDs.Knot provides a separate fast caching server and resolver library alongsideits authoritative server.
Authoritative nameserver and caching/recursive nameserver functions areseparated for good reason. A nameserver's query result cache can be"poisoned" by queries that forward to malicious external servers, soif you don't allow the authoritative nameserver to answer queries forother domains, it cannot be poisoned and its answers for its own domain canbe trusted.
A software monoculture means running identical software like BIND9 everywhererather than different software providing identical functionality andinteroperability. This is bad for the same reasons we eventually will loseour current popular species of banana—being genetically identical, allbananas everywhere can be wiped out by a single infectious agent. As withfruit, a bit of genetic diversity in critical infrastructure is a good thing.
In this article, I describe how to install and minimally configure Knotto act as your home lab's local domain master and slave servers. I willsecure zone transfer using Transaction Signatures (TSIG). Although Knotsupports DNSSEC, I don't discuss it here, because I like you and want youto finish reading before we both die of old age. I assume you already knowwhat a DNS zone file is and what it looks like.
You may download the latest version (2.8.x as I write) source tarball viahttps://www.knot-dns.cz/download and build it yourself using the ubiquitousconfigure;make;make install incantation. I recommend running the latestKnot version if you intend to have your resolver face the public internet. Ifound that, to build Knot on Ubuntu 18.04, I needed to install the packagespkg-config,libgnutls28,liburcu-devandlibedit-dev in addition to thestandard essential build toolkit. Knot's website has furtherrequirements, which CentOS 7 and Ubuntu 18.04 appear to meet. The tar extractand build process also oddly demanded to make some hard file links. Buildingas an unprivileged user was successful despite the hard link failure errors.
For my home lab, the 2.6.x package in Ubuntu "universe" and EPELrepos is adequate. To install it on Ubuntu 18.04, I enabled the "bionicuniverse" repo in my /etc/apt/sources.list and did this:
$ sudo apt update$ sudo apt install knotOn CentOS 7, I would have run the commands:
$ sudo yum install epel-release$ sudo yum install knotI can now proceed to configure the Knot master instance. I hate readingBIND9 config files, and although I know the major distros are trying to behelpful, I particularly hate the sliced and diced versions they provide.Knot.conf is a breeze by comparison. Knot's mercifully terse single-fileconfiguration uses YAML format. The Knot package deploys a sampleconfiguration in /etc/knot.conf. I moved that file aside and created a freshone using my preferred editor, vi:
$ sudo mv /etc/knot.conf /etc/knot.conf-save$ sudo vi /etc/knot.confMy home network is cpu-chow.local; name yours as you see fit. Since nobodybut you will recognize this server as authoritative, you can choose your TLDas well. You feed this domain to caching nameservers in your home lab byconfiguring them to forward queries explicitly for your domain to yourauthoritative resolver.
The first section defines the server's presence on the host and network.Section names start at column 1, entries are indented four spaces:
server: identity: dns1.cpu-chow.local listen: [ 127.0.0.9@53, 172.28.1.22@53 ] user: knot:knot rundir: /run/knotIn the server section, I'm telling Knot its hostname and to run on port 53of the local interface but at a different address, 127.0.0.9. Since Knot canresolve queries only for cpu-chow.local, it has little use serving from thedefault 127.0.0.1; besides, my host's caching nameserver is therealready. I'm also directing it to listen on the host's lab networkaddress, 172.28.1.22. My lab network is 172.28.1.0/24, and I want to offerauthoritative nameservice for cpu-chow.local to the other hosts in my lab. Icould instead offer the authoritative server to my host's caching serveronly and have that caching server listen on the lab net IP and serve all theother hosts' query needs if I desired.
Installing Knot created a user id knot, and I'm directing Knot to run asthat UID/GID for least-privilege best practice. Therundir will be the homeof Knot's management socket. If you run multiple Knot instances, use aunique /run directory for each.
Afterrundir, I insert a blank line to signal the section's end and startthe key section to define my TSIG key. Note thatid has a dash in column 3.That is YAML, and it means that what follows is specifically associated withkeytsigkey1. alone:
key: - id: tsigkey1. Algorithm: hmac-sha256 secret: base64-keyvalueTo define another key, add anotherid lineimmediately after the first secret line.
This is the secret that authorized slave servers will provide when theyrequest an administrative zone transfer (AXFR), a request to sync up with themaster. I've given my arbitrarily named key a fully lowercase namefollowed by a period to ensure interoperability with other DNS server softwarelike PowerDNS, which seemed always to lowercase and append a period towhatever key name I gave it when I ran it as a slave to a Knot master.
The secret is a randomly generated Base64 value. Knot includes thekeygenutility to generate the key section for you, and you can paste the outputinto your config file:
$ keymgr -t tsigkey1.key:- id: tsigkey1. algorithm: hmac-sha256 secret: oxRKAUfGN3R6fGjWX/V+i4rjCl1zRuYslX0c4se+GWs=Another blank line, and I move on to the template section, which definescommon presets that can be applied in other sections. You add multipletemplates just like multiple keys. The template section and the template iddefault must be present in knot.conf, or else Knot will emit a cryptic errormessage when you start it:
template: - id: default storage: "/var/lib/knot"default is a special template that is applied automatically; other templatesmust be referenced in a section to apply there. I am declaring here that bydefault, all files to be read are in /var/lib/knot. I intend to usensupdateto manage my zones, so keeping them in /etc/knot will not be appropriate(nsupdate is beyond the scope of this article.)
And now I define my authorized slaves with the remote section. Thissession associates a host and various attributes with a name you can uselater in the config:
remote: - id: slave1 address: 127.0.0.19@53 key: tsigkey1. - id: slave2 address: 172.28.1.20@53 key: tsigkey1.id is an arbitrary name. In addition to a remote slave on lab host172.28.1.2, I will run a slave on the master host at 172.0.0.19 toilluminate an arcane Linux networking issue.
Theacl section defines the server's access control lists(ACLs)—to whom Knot will listen when they send administrative requeststo it:
acl: - id: acl_axfr address: [ 127.0.0.0/24, 172.28.1.20 ] action: transfer key: tsigkey1. - id: acl_upme address: 127.0.0.0/24 action: update key: tsigkey1.I've configured two ACLs, one to receiveAXFR requests from slavesand the other to facilitatensupdate requests originating on the local host.Each will use the same key, but they don't have to.
So why did I employ a /24 mask onacl_xfer? Shouldn't it be 127.0.0.19?Indeed, it should, but Linux networking has a small quirk. Sometimes when mylocalhost slave sends a request, the data will appear to be coming from themain IP associated with the lo interface: 127.0.0.1. Before a websearch revealed this oddity, I stared at my logs in disbelief and pored overtcpdump output for some time when the master kept denyingmysteriousAXFRrequests from 127.0.0.1. Several DNS server software packages have a configoption to specify the source address for slave transmissions. I have yet tofind such an option in Knot. I'm causing the issue here because I'mbeing cheeky in my use of 127.0.0.* addresses; this would not happen if Iused a lab or public network address. So I'm comfortable specifying arange for localhost on my home lab.
How, during the above incident, did I get Knot to tell me why it wasn'tworking? I ratcheted up the logging level. The log section controls whatgets logged and where it goes:
log: - target: syslog any: infoThis config emits all log entries atinfo level and worse, and sends them tosyslog. To get debug-level entries as well and dump it out to your screen(running Knot in the foreground), I used this config instead:
log: - target: stdout any: debugtarget also can be stderr or a filename.
I'm now ready to declare my authoritative zones with the zone section.For this article, I'm just setting up one zone:
zone: - domain: cpu-chow.local file: "cpu-chow-local.zone" notify: slave1 acl: acl_axfr acl: acl_upme semantic-checks: on disable-any: on serial-policy: incrementNote that a period is not required at the end of the domain name. The fileattribute does not allow a path; the default template supplies the storageattribute, /var/lib/knot, the location of cpu-chow.local.zone.
notify designates to which remote id my master will send a"notify" message advising them that they should promptly respond with anAXFRrequest. The firstacl designates the IP addresses to whom the master willlisten forAXFR requests and the second fornsupdate requests. I could map anon-default template here by adding atemplate: template-id lineunder this zone.
I have included some other attributes in the zone to illustratebest practices:semantic-checks does extra syntax checking on the zone file.disable-any alters Knot's response to, say, a-tANY query toprevent DNS zone-reflection attacks.serial-policy ensures that a dynamicupdate will trigger a serial number increment in the zone file.
I saved the file, set its owner toroot:knot and permissions to 640. I cannow start Knot, either via systemd:
$ sudo systemctl restart knot$ sudo systemctl status knotor by running it in the foreground with great verbosity:
$ sudo /usr/sbin/knotd -vvv -c /etc/knot/knot.confNote that systemd may not immediately report that Knot startup has failed, sofollowing up with a status check is a good practice.
On my local caching server at 127.0.0.1, I update the config to tell it toconsider my master at 127.0.0.9 as authoritative for my zone. Since I'mrunning PowOerDNS Recursor, I edit the file /etc/powerdns/recursor.conf:
forward-zones-recurse=cpu-chow.local.=127.0.0.9I'll do the same elsewhere in my lab, using the lab net address172.28.1.22 instead.
Let's look at a config for a slave server on 127.0.0.19. I'll callit /etc/knot/slave.conf, same owner and permission as the master config.Since it is a second Knot instance, I'll need to create a secondrundirand storage location. Since it's a slave Knot, let's call itsnot:
$ sudo mkdir -p /run/snot /var/lib/snot$ sudo chown knot:knot /run/snot /var/lib/snot$ sudo chmod 755 /run/snot /var/lib/snotAnd here is /etc/knot/slave.conf:
server: identity: dns2.cpu-chow.local listen: 127.0.0.19@53 user: knot:knot rundir: /run/snotkey: - id: tsigkey1. algorithm: hmac-sha256 secret: oxRKAUfGN3R6fGjWX/V+i4rjCl1zRuYslX0c4se+GWs=template: - id: default storage: /var/lib/snotremote: - id: master1 address: 127.0.0.9@53 key: tsigkey1.acl: - id: acl_axfrnfy address: 127.0.0.0/24 action: notify key: tsigkey1.log: - target: stdout any: debugzone: - domain: cpu-chow.local master: master1 acl: acl_axfrnfyIt looks quite similar to the master. Note theacl allowing the slave toaccept the notify message from the master. I have logging set todebug-leveland standard output because I intend to run it in foreground.
You may create a systemd unit file to start the slave if you wish (beyondthis article's scope). I'm running it manually here:
$ sudo /usr/sbin/knotd -vvv -c /etc/knot/slave.confI can control a running instance ofknotd by using the control program/usr/sbin/knotc, thus:
$ sudo /usr/sbin/knotc -c config-file [ command ]Specifying the config file tellsknotc whichrundir contains the socket towhich to connect. Use theknotc commandzone-notify on the master to have itnotify slaves to request anAXFR, orzone-flush to flush the cache. Manyother commands are available, use--help to see them.
I have barely scratched the surface of Knot's capabilities; it really isdesigned to handle a full TLD with ease, so it can handle your load.Consider using it alongside your existing DNS software to avoid a DNSsoftware monoculture in your organization.
Now that you've been introduced to Knot DNS and walked through an examplemaster and slave configuration, you can install, configure and evaluate itfor yourself. And you may like it enough that it will make your chest hairsall crispy, just like the Festrunk brothers.
Thomas Golden (tomg16.lj@cpu-chow.com) has been a Linux sysadmin for morethan20 years and was an OpenVMS system programmer and admin before that.






