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
:
launch=gmysql
gmysql-dnssec
gmysql-host=localhost
gmysql-port=3306
gmysql-dbname=pdns
gmysql-user=pdns
gmysql-password=supersecret
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 @127.0.0.1 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
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 2800
;; QUESTION SECTION:
;www.a.aa. IN A
;; ANSWER SECTION:
www.a.aa. 86400 IN A 1.1.1.0
www.a.aa. 86400 IN RRSIG A 5 3 86400 20110127000000 (
20110113000000 58590 a.aa.
eUv+uEbDEUBgaQy8hk9taln9swJHkblIgnjG93b3Hj1B
yWnj7eHv7AxN6sYiQV9zASRB0DjujCqoPeDI4sdsdb0o
crrEhdHGsTTvHZ+3iJeXnFJ1p46FJOyjoydXZ8Cmk7ix
cVf86g3JGiU135Rf5P6QU2Kl68YAf3orKGpUIqw= )
;; Query time: 1 msec
;; SERVER: 192.168.1.182#53(192.168.1.182)
;; 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
keys:
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.