Setting up PowerDNS 4.1 to do authoritative and recursive name service. ---------------------------------------------------------------------- The PowerDNS IRC channel regularly sees queries about transitioning from a single process offering authoritative and recursive service, to a mixed model running the authoritative and recursive servers on the same host. This is certainly not something you'd want to do at scale, but for small installations, like my home network, it makes sense. This is a description of my situation, and how I've set it up. I maintain the following domains: hamartun.priv.no helbekkmo.net helbekkmo.no helbekkmo.priv.no tones.priv.no 0-31.27.71.193.in-addr.arpa 0.0.4.0.9.c.0.c.8.0.1.0.0.2.ip6.arpa 201.27.172.in-addr.arpa 202.27.172.in-addr.arpa 203.27.172.in-addr.arpa 204.27.172.in-addr.arpa The first five are normal domains, officially mine, delegated to me at my primary name server, barsoom.hamartun.priv.no. Then, there's the in-addr.arpa domain that contains reverse PTR records for the 32 addresses in my /27 official IPv4 network, and the ip6.arpa domain that covers the /56 IPv6 one. The last four are RFC1918 networks I use internally, with NAT between them and the world. My main domain is hamartun.priv.no, which ends up containing, among other things, a mixture of official and RFC1918 A records. This used to all be served by the same BIND (named) process, on the NetBSD system (barsoom) that's always on, and runs all the various services that I need to have continually available. That named was also the recursive name server for everything on my network. Then I upgraded to PowerDNS, and then the PowerDNS authoritative server stopped being a recursor. So, here's what I did on barsoom, to keep everything unchanged everywhere else, and still have that single system be the only one that always has to be running: dnsdist listens on the official IPv4 and IPv6 addresses, and receives queries from inside and outside. It's what maintains the "single name server" illusion for all the other stuff. Meanwhile the authoritative server and the recursor run on non-standard ports on the loopback interface, only receiving queries that are directed at them from dnsdist. Of course, when they themselves initiate conversations (the recursor to, well, recurse, and the authoritative server to announce new data), they do so from barsoom's official addresses. First, the 'pdns.conf' for the authoritative server. It listens only on port 5301, on localhost, but sends its update announcements from the official addresses. It must allow AXFR requests locally, because they will be relayed in by dnsdist. (All the example files shown here are shortened from my actual, running, configurations, keeping only what's relevant to the topic at hand.) local-address=127.0.0.1 local-port=5301 query-local-address=193.71.27.8,2001:8c0:c904:10::8 allow-axfr-ips=127.0.0.1/32 Now, the recursor. It hides out just like the authoritative server, and is just a recursor - except that it must forward the zones that I maintain locally. These fall into two categories: the RFC1918 ones are explicitly forwarded only to the authoritative server, but the "real" ones have more than one forwarding address, and these are the actual addresses of the name servers that serve each zone. This way, if the authoritative server is running, it will be handed all of this, but if it isn't, the official zones will be handled by secondary name servers elsewhere. This makes bootstrapping barsoom easier. :) local-address=127.0.0.1 local-port=5302 allow-from=127.0.0.1 query-local-address=193.71.27.8,2001:8c0:c904:10::8 forward-zones=201.27.172.in-addr.arpa=127.0.0.1:5301 forward-zones+=202.27.172.in-addr.arpa=127.0.0.1:5301 forward-zones+=203.27.172.in-addr.arpa=127.0.0.1:5301 forward-zones+=204.27.172.in-addr.arpa=127.0.0.1:5301 forward-zones+=0.0.4.0.9.c.0.c.8.0.1.0.0.2.ip6.arpa=127.0.0.1:5301 forward-zones+=hamartun.priv.no=127.0.0.1:5301;193.75.75.1 forward-zones+=8.0-31.27.71.193.in-addr.arpa=127.0.0.1:5301;193.75.75.1 forward-zones+=helbekkmo.priv.no=127.0.0.1:5301;193.75.75.1 forward-zones+=tones.priv.no=127.0.0.1:5301;193.75.75.1 forward-zones+=helbekkmo.no=127.0.0.1:5301;194.63.248.53;2a01:5b40:0:248::53 forward-zones+=helbekkmo.net=127.0.0.1:5301;194.63.248.53;2a01:5b40:0:248::53 Finally, there's dnsdist. It listens to the real addresses, and keeps two pools of servers behind it. One holds the authoritative server only, the other has the recursor, and, at lower priority, 8.8.8.8. This punts recursive queries to Google in a pinch, again to make things a bit more robust, especially during boot. A simple netmask group decides who gets recursive service (my official nets, and the RFC1918 nets I use). Then there's a rule structure that ensures that only my actual secondary name servers are allowed to do zone transfers. Anything else goes to the authoritative server. setLocal('193.71.27.8:53') addLocal('[2001:8c0:c904:10::8]:53') setACL({'0.0.0.0/0', '::/0'}) newServer({address='127.0.0.1:5301', pool='auth', order=1}) newServer({address='127.0.0.1:5302', pool='recursor', order=1}) newServer({address='8.8.8.8:53', pool='recursor', order=2}) setServerPolicy(firstAvailable) recursive_ips = newNMG() recursive_ips:addMask('127.0.0.0/8') recursive_ips:addMask('193.71.27.0/27') recursive_ips:addMask('172.27.0.0/16') recursive_ips:addMask('::1/128') recursive_ips:addMask('2001:8c0:c904::/56') addAction(NetmaskGroupRule(recursive_ips), PoolAction('recursor')) addAction(AndRule({OrRule({QTypeRule(dnsdist.AXFR), QTypeRule(dnsdist.IXFR)}), NotRule(makeRule('194.63.248.53/32')), NotRule(makeRule('193.75.75.1/32')), NotRule(makeRule('193.75.110.142/32'))}), RCodeAction(dnsdist.REFUSED)) addAction(AllRule(), PoolAction('auth'))