setting up powerdns slave / untrusted host
When migrating our nameserver setup to start using DNSSEC, a second requirement was to offload a resolver to somewhere off-network.
You want your authoritative nameservers to be distributed both accross different geographical regions, networks and top level domains. That means, don't do this:
ns1.thedomain.com
- datacenter X in Groningenns2.thedomain.com
- datacenter X in Groningen
Do do this:
ns1.thedomain.com
- datacenter X in Groningenns2.thedomain.org
- datacenter Y in Amsterdam
In our case, we could use a third nameserver in a separate location: a virtual machine hosted by someone other than us. Let's call it ns3.thedomain.io.
Between our primary two nameservers we were happily using MySQL replication to share the updates. PowerDNS works perfectly using NATIVE mode and master-master or master-slave replication.
However, now that we've started using DNSSEC we must worry about our private keys not leaking. For starters we ensure that we use TLS for the MySQL replication between ns1 and ns2. And secondly: we cannot just trust any remote virtual machine vendor with our private DNS keys. That means no MySQL slave replication to the new ns3.thedomain.io.
Luckily, PowerDNS will also function in regular slave mode, and configuring it is not hard.
On ns1: /etc/powerdns/pdns.d/pdns.local.conf
# Make sure we send updates to slaves.
master=yes # we're a master for ns3.thedomain.io
# Add the IP 55.55.55.55 of ns3.thedomain.io.
allow-axfr-ips=127.0.0.0/8,::1,55.55.55.55
# Don't notify all slaves found through DNS. If we do not set this,
# ns1 would start pushing updates to both ns2 and ns3. And ns2 does
# not want any: it operates in "native" master mode, taking the config
# out of the MySQL db directly.
only-notify=55.55.55.55 # the IP of ns3.thedomain.io
On the new ns3.thedomain.io slave, we configure MySQL support as
usual, without any replication. Add this to the
/etc/powerdns/pdns.d/pdns.local.conf
# We slave off ns1.thedomain.com (or in fallback case from ns2.thedomain.org);
# see the supermasters table in mysql pdns schema.
slave = yes
Populate the supermasters
table on ns3:
mysql> select * from supermasters;
+-------------+-------------------+------------+
| ip | nameserver | account |
+---------------+-----------------+------------+
| 44.44.44.44 | ns1.thedomain.com | TheDomain |
+-------------+-------------------+------------+
Almost there.
At this point we need to do three things:
-
Replace the NATIVE type with MASTER for the relevant domains:
UPDATE domains SET type = 'MASTER' WHERE type = 'NATIVE' AND name IN ('...');
Without this change, PowerDNS will not notify the slaves of any updates!
-
Add an ns3.thedomain.io NS record to the relevant domains (using pdnsutil or SQL and a manually updated serial).
-
Add the third nameserver to the TLD — how you do this is specific to your registrar.
At this point, your new PowerDNS on ns3.thedomain.io should start receiving records. You can check the database and/or syslog.
If some domains fail to appear — you did update the serial right? —
you can force an update from ns1 using:
pdns_control notify somedomain.tld
And, where on ns1 and ns2 you have the sensitive private key material and on-the-fly DNSSEC signing, on ns3 you get presigned (by ns1) data.