PowerDNS is a very popular DNS server. Until now there was little to be seen on it implementing DNSSEC natively, which is why using tools such as OpenDNSSEC for PowerDNS was needed. It has been a while coming: Bert Hubert and contributors have done a tremendous amount of work and have finally implemented DNSSEC into the very popular PowerDNS DNS server. I’ve taken the new PowerDNS for a small test drive.

I installed the program on an Ubuntu test server, overwriting the existing PowerDNS binaries. The database schema (MySQL or SQLite3) used by PowerDNS needs patching: two columns (ordername and auth) are added to the records table, and two new tables named domainmetadata and cryptokeys are created. The former contains NSEC3 parameters; the latter is used for key storage (see below).

I then instructed pdns_server to actually DNSSEC-enable the appropriate back-end (actually this tells it the DNSSEC schema is in place), by adding a single line to pdns.conf:


After launching the server I see … nothing. No answers to queries. A log message indicates that a rectify with the newly included pdnssec utility is to be issued, and the documentation recommends you do this for all zones, even unsigned zones. This populates the ordername and auth columns in the records table, after which normal queries are possible again.

    pdnssec rectify-zone a.aa

So far so good, and my PowerDNS server is back to normal; it answers plain queries as it used to.

Now for the fun part.

To enable DNSSEC on a zone, I then have PDNS create a Zone Signing Key (ZSK) and a Key Signing Key (KSK) with the following commands (additional algorithms are supported):

    $ pdnssec add-zone-key a.aa zsk
    configname: '/etc/powerdns/pdns.conf'
    Adding a ZSK with algorithm = 5
    $ pdnssec add-zone-key a.aa ksk
    configname: '/etc/powerdns/pdns.conf'
    Adding a KSK with algorithm = 5

These keys are created in the MySQL back-end database (and are thus replicated to slave servers). After a few seconds I query the server for a DNSSEC answer:

    $ dig +dnssec +multiline @  www.a.aa
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40961
    ;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
    ;; WARNING: recursion requested but not available
    ; EDNS: version: 0, flags: do; udp: 2800
    ;www.a.aa.          IN  A
    www.a.aa.       86400 IN A
    www.a.aa.       86400 IN RRSIG A 5 3 86400 20110127000000 (
                    20110113000000 58590 a.aa.
                    cVf86g3JGiU135Rf5P6QU2Kl68YAf3orKGpUIqw= )
    ;; Query time: 1 msec
    ;; SERVER:
    ;; WHEN: Thu Jan 13 12:03:48 2011
    ;; MSG SIZE  rcvd: 217

Very nice.

There is one thing missing. I need the DS resource records to give to the parent zone maintainer. These I get with the pdnssec utility. (Output truncated for brevity)

    $ pdnssec show-zone a.aa
    configname: '/etc/powerdns/pdns.conf'
    Zone has NSEC semantics
    ID = 4 (KSK), tag = 57698, algo = 5, bits = 2048    Active: 1
    KSK DNSKEY = a.aa IN DNSKEY 257 3 5 AwEAAZfSTDIZ0.....
    DS = a.aa IN DS 57698 5 1 4e12372b5e029dfb5567d36dd8427c61a217505d
    DS = a.aa IN DS 57698 5 2 f4462cb09a8c05ca43c13774b307f60bd40129cf211413c060d9e5c39aa98498
    ID = 3 (ZSK), tag = 58590, algo = 5, bits = 1024    Active: 1

The key ID numbers correspond to the id column in the cryptokeys table:

    SELECT c.id, name, flags FROM cryptokeys c, domains d WHERE d.id = c.domain_id;
    | id | name | flags |
    |  3 | a.aa |   256 |
    |  4 | a.aa |   257 |

and we see the flags column (256 == ZSK and 257 == KSK).

As shown by the show-zone command above, the zone has been signed with NSEC semantics, which means the zone is “walkable”. To convert that to NSEC3 semantics, I use pdnssec set-nsec3 a.aa, and I can revert the zone to NSEC with pdnssec unset-nsec3 a.aa.

DNSSEC resource records are not stored in the database, but are created on- the-fly, but are heavily cached. I like this because it keeps the database content clear of the additional “clutter”. Keys are, as described above, stored and replicated from (MySQL-) master to server. Nevertheless, a zone transfer (AXFR) from a DNSSEC-enable PowerDNS will of course transfer all resource records, including the DNSSEC RRsets. The validity period for RRSIGs in PowerDNS starts at most a week in the past, and continues at least a week into the future.

As far as rolling keys, the operational instructions are quite easy to follow.

At a first glance the code gives a very good impression and is a great addition to the tools we now have available for signing DNSSEC zones. A few first thoughts:

  • On-the-fly signing costs CPU time. PowerDNS uses all CPU cores for generating RRsigs so this will help, but it remains to be seen how many requests per second PowerDNS can generate.
  • I like the fact that keys are in the back-end database and not on the file system because I can put the MySQL server behind an additional firewall to add a further level of security. Of sorts.
  • Enabling DNSSEC on zones served by PowerDNS becomes as easy as automatic DNSSEC signing on BIND. It isn’t quite as “automagic” as using Phreebird but comes very close.
  • PowerDNS should automate rectify-zone itself; that is going to cause a lot of grief otherwise.
DNS, CLI, dnssec, and pdns :: 13 Jan 2011 :: e-mail