This is the third post in a series that highlights interesting new features of the PowerDNS 4.x.x and dnsdist 1.x.x releases.
I (Bert) have to admit something. Even though I set out to write a database driven nameserver 16 years ago.. I have never actually liked maintaining domains in a database. Of course, most large scale PowerDNS users have web-interfaces and scripts to provision the database. But out of the box, you could either use the pretty cool ‘BIND’ backend in PowerDNS.. or edit SQL.
Today I’m proud to announce that for the first time I personally enjoy editing my domains with PowerDNS. For completeness, this post will outline the full process of setting up a redundant PowerDNS server setup.
Basic setup (master)
First, install a 4.x.x version of PowerDNS, most easily obtained as packages from our repositories as found on https://repo.powerdns.com/. For this demo, install packages ‘pdns-server’ (‘pdns’ on RHEL/CentOS) and ‘pdns-backend-sqlite3’ (although these examples work just as well for the MySQL, PostgreSQL and ODBC backends).
Next, we need to create a database, in this case sqlite3 :
|# sqlite3 /etc/powerdns/powerdns.sqlite3 < /usr/share/doc/pdns-backend-sqlite3/schema.sqlite3.sql|
Then we configure PowerDNS to listen on all IP addresses, and to run with the database we just generated. This file goes in /etc/powerdns/pdns.conf:
We can now start PowerDNS, for example with:
service pdns start.
To verify that everything works, run:
dig chaos txt version.bind @127.0.0.1 +short
If everything is ok, it will tell you the exact version of PowerDNS you are running (this can of course be disabled).
Up to here, this is how installing PowerDNS Authoritative Server has worked for years.
The new command-line based zone editing features
To create a new domain name, operators typically copy some known good zone file from somewhere, and load that up. We’ve automated this process like this:
|# pdnsutil create-zone example.com ns1.example.com|
|Creating empty zone 'example.com.'|
|Also adding one NS record|
|# pdnsutil add-record example.com ns1 A 192.168.1.2|
|ns1.example.com. IN A 3600 192.168.1.2|
|# pdnsutil list-zone example.com|
|example.com. 3600 IN NS ns1.example.com.|
|example.com. 3600 IN SOA ns1.example.com hostmaster.example.com 1 10800 3600 604800 3600|
|ns1.example.com. 3600 IN A 192.168.1.2|
|$ dig +noall +answer ns1.example.com @127.0.0.1|
|ns1.example.com. 3600 IN A 192.168.1.2|
These few commands create a well configured zone, and add a new record to it. Finally, the ‘dig’ line verifies that all is good.
We can further edit the zone with
Note how this command actually runs a check on your changes to see if your zone still makes sense, and prompts you to edit some more or start over if it doesn’t look right. This uses the built-in DNS knowledge of PowerDNS, something which was frequently lacking in earlier scripts to update zone contents.
The pdnsutil commands ‘create-zone’, ‘edit-zone’, ‘list-zone’, ‘add-record’, ‘replace-rrset’, ‘remove-rrset’ thus form a complete way to edit a zone safely – since PowerDNS actually checks if what you entered makes DNS sense before committing it to the database.
But wait, there’s more
In the ‘pdnsutil edit-zone’ session above, we added an A record for ns2.powerdns.com, but we did not add an NS record to the zone yet. To do this, execute:
pdnsutil add-record example.com @ NS ns2.example.com'.
When that is done, we tell the PowerDNS master server to allow that slave to actually transfer the zone by executing:
pdnsutil set-meta example.com ALLOW-AXFR-FROM AUTO-NS. This tells PowerDNS: allow any IP address listed as a nameserver for this domain to transfer it.
Finally, we tell PowerDNS this is a ‘master’ zone for which we should send out out notifications by executing:
pdnsutil set-kind example.com master
To verify that it all worked, we use
|# pdnsutil show-zone example.com|
|This is a Master zone|
|Last SOA serial number we notified: 0 != 1 (serial in the database)|
|Zone is not actively secured|
|No keys for zone 'example.com.'.|
Now we need to install PowerDNS on the slave server, and this is just like for our master, but we add the word ‘slave’ to pdns.conf. Please see above.
Once PowerDNS is installed and setup, we run:
pdnsutil create-slave-zone example.com 192.168.1.2, where 192.168.1.2 is the IP address of our master server ns1.powerdns.com.
PowerDNS periodically checks the database for new slave zones, and within a minute it will pick up the new zone:
|Jan 29 22:35:45 1 slave domain needs checking, 0 queued for AXFR|
|Jan 29 22:35:45 Received serial number updates for 1 zones, had 0 timeouts|
|Jan 29 22:35:45 Domain 'example.com.' is stale, master serial 1, our serial 0|
|Jan 29 22:35:45 Initiating transfer of 'example.com.' from remote '192.168.1.2:53'|
|Jan 29 22:35:45 AXFR started for 'example.com.'|
|Jan 29 22:35:45 Transaction started for 'example.com.'|
|Jan 29 22:35:45 AXFR done for 'example.com.', zone committed with serial number 1|
If you are in a hurry, execute
pdns_control retrieve example.com and the zone will be slaved immediately.
Making further changes on the master server
Meanwhile, if we make a change on the master server, we need to bump the SOA serial number to make the DNS master/slave ritual aware of it. Do so either in ‘edit-zone’, or like this:
pdnsutil increase-serial example.com. And again, PowerDNS will pick this up shortly and send out notifies. And like on the slave, if you are in a hurry, execute:
pdns_control notify example.com.
What about DNSSEC?
All of the above works just as well with DNSSEC. Simply issue
pdnsutil secure-zone example.com on the master server, bump the serial number, and inform your registrar of your new DS record (as shown by
pdnsutil show-zone example.com).
PowerDNS has always offered classic zonefiles for your editing delight. Most large deployments have used various (web)tools to fill out the database with DNS details. But if like me you like a solid set of command line tools, PowerDNS Authoritative Server 4.x now has you covered!