NSD (version 3) is a blindingly fast authoritative DNS server created by NLnetLabs, the fine people who also created the Unbound recursive server. Quoting myself:

NSD uses master zone files (the same files as those used by BIND). You compile these into a binary database using NSD’s zone compiler. Pre-compiling zone data lets NSD start up very quickly. NSD evolved out of a server designed to power the K.ROOT-SERVERS.NET installation. NSD is authoritative only, i.e. it will not answer queries for which it isn’t responsible. It cannot act as a caching or recursive server. NSD can be set up as a master name server and as a slave name server.

A new version called NSD4 is on the horizon, and I want to look at some of its new features.

As described above, one of NSD3’s major features is that zone data is “compiled” into a database from which NSD3 serves replies. While it is precisely that what makes NSD3 so fast, it is simultaneously one of its major drawbacks: adding new zones to NSD3 is a bit of a convoluted process: nsd.conf has to be updated, the internal database has to be “recompiled”, and NSD3 has to be reloaded.

While this is fine for environments with a relatively static number of zones, it has always been a drawback for organizations (e.g. hosters) with many zones that come and go. NSD4 addresses this problem, and that is what I’m going to look at here. (BTW, if you currently use NSD3, migration to NSD4 ought to be quite easy.)

Configuration of NSD4 is mostly unchanged, but there are some new bits in nsd.conf:

        database: "/usr/local/nsd4/etc/nsd/nsd.db"
        zonesdir: "/usr/local/nsd4/etc/nsd/zones"
        zonelistfile: "/usr/local/nsd4/etc/nsd/zones.list"

        control-enable: yes
        control-interface: ""
        control-port: 8952
        server-key-file: "/usr/local/nsd4/etc/nsd/nsd_server.key"
        server-cert-file: "/usr/local/nsd4/etc/nsd/nsd_server.pem"
        control-key-file: "/usr/local/nsd4/etc/nsd/nsd_control.key"
        control-cert-file: "/usr/local/nsd4/etc/nsd/nsd_control.pem"

        name: "sl"
        zonefile: "sl-hosts/%s.zone"
        request-xfr: NOKEY
        request-xfr: NOKEY
        provide-xfr: NOKEY

        name: "pdns"
        zonefile: "slaves/%1/%s.zone"
        request-xfr: NOKEY
        request-xfr: NOKEY

The server stanza describes server settings, and most of those are unchanged as are the settings for specifying master zones.

The old nsdc utility from NSD3 has been replaced with a remote-capable tool aptly named nsd-control which operates similarly to Unbound’s unbound-control: it also requires a pair of SSL certificates to talk to the server; you either provide your own, or you create them up with the nsd-control-setup shell script.

All new, and this is where I find it gets exciting, are the zonelistfile directive (in the server stanza) and the pattern directives, which allow us to introduce new slave zones into NSD4 without touching its configuration files. (This is similar in concept to adding zones to a BIND name server with addzone if less messy because I can “predefine” master servers, TSIG keys etc., which I cannot do for BIND.)

Think of patterns as groups. Here I have a pattern (or a group) called “sl”, and another called “pdns”. Each of these provides a directory (which can be different) and a number of master servers responsible for the “pattern”.

NSD4 queries groups of master servers

If I now launch the following command, NSD4 will add the new slave zone to the zonelistfile and will attempt a zone transfer from the slave servers specified in the pattern I defined as “pdns”:

$ nsd-control addzone big.aa   pdns

The zone is transferred into NSD4’s internal database, and it is written out on demand with nsd-control write. Here’s a snippet from the server log:

[1359738155] nsd[6825]: info: new control connection from
[1359738155] nsd[6825]: info: remote control connection authenticated
[1359738155] nsd[6825]: info: control cmd:  addzone big.aa pdns
[1359738155] nsd[6825]: info: remote control operation completed
[1359738155] nsd[6825]: info: Handle incoming notify for zone big.aa
[1359738155] nsd[6825]: info: xfrd: zone big.aa written received XFR from with serial 35 to disk
[1359738155] nsd[6825]: info: xfrd: zone big.aa committed "received update to serial 35 at 2013-02-01T17:02:35 from"
[1359738155] nsd[6830]: info: zonefile slaves/b/big.aa.zone does not exist
[1359738155] nsd[6833]: info: zone big.aa. received update to serial 35 at 2013-02-01T17:02:35 from of 1361 bytes in 0.000412 seconds
[1359738155] nsd[6825]: info: Zone big.aa serial 0 is updated to 35.
[1359738248] nsd[6825]: info: control cmd:  write
[1359738248] nsd[6825]: info: remote control operation completed
[1359738248] nsd[6836]: info: writing zone big.aa to file slaves/b/big.aa.zone~

I can specify tokens to instruct NSD4 where I want zone files written to. The following magic characters are allowed in zonefile, and required directories are created automatically. For a zone called “hosts.example.net”:

  • %s specifies the zone name ("hosts.example.net")
  • %1 is the first character of zone name ("h"), %2 the second ("o"), and %3 the third ("s")
  • %z names the top-level domain label of zone ("net"), %y the next ("example"), and %x the third ("hosts")
  • if a label or character does not exist you get a dot (".") (Careful: you probably don’t want that as a path component!)

Zones can also be removed from a running NSD4 instance: the delzone command does that. As far as adding new master zones, the procedure is similar to how it used to be: master zones are added by creating the zone file, adding them to nsd.conf and using reconfig to have the daemon reconfigure itself.

Another feature you might be interested in (because it’s being discussed a lot) is rate-limiting: NSD4 implements DNS Response Rate Limiting as proposed by Paul Vixie and Vernon Schryver. I’ll save that for a later posting.

NSD4 is still in beta, but you can download and experiment with it. If you need help, the mailing-list is the place to go to.

DNS and NSD :: 01 Feb 2013 :: e-mail