PowerDNS is a dynamic nameserver, with a ton of backends. If the supplied backends aren’t flexible enough, our architecture enables operators to write their own, or to use one of our forwarding backends (Pipe and Remote), which can send PowerDNS queries over a pipe, a UNIX domain socket, an HTTP connection or even a ZMQ link.
Over time, many operators have done just that, and this allows you to mix a ‘real’ nameserver, with everything you can expect from that, with a custom data source.
Very often however (weekly at this point!), we get questions from users confused about our backends:
- Why does my backend get ANY queries, when no ANY queries are sent to the nameserver?
- How do I generate an NXDOMAIN response from my backend?
- Why do I get SOA queries, even for domains not in my backend?
- Why does PowerDNS ignore the records my backend sent back to put in the packet?
- Why do I get more backend queries than DNS queries (sometimes)?
- Why do I get *way less* backend queries than DNS queries at other times?
- Why are backends launched for AXFRs?
All of these questions stem from a misunderstanding what a PowerDNS backend is, possibly combined with the fact that people want things that aren’t easily achieved from a backend. We may not have been doing a sufficiently good job explaining PowerDNS backends.
To explain, we must first do away with what a PowerDNS backend is not. It is for example not this:
In this model, packets from the internet get handed over to a backend, and the backend drafts an answer packet for PowerDNS to send out. We do have functionality that does that, more about which later, but backends are not it. Backends get DNS queries and return data, or perhaps none if there isn’t any.
So why did we not build it as above? It turns out DNS needs a lot of logic. So for example, if a nameserver gets a question for ‘www.powerdns.com’, it has to figure out if it is even authoritative for that question, or in other words, does it have a zone with relevant data for that query? To figure that out, the RFC algorithm tells us we must find the best zone that matches the query. Initially this could be ‘www.powerdns.com’, and if we don’t have that zone, we should look for ‘powerdns.com’, then ‘com’ and finally perhaps a root zone.
Once we have the best zone ready, we must check if a ‘www’ record exists, if there is perhaps a delegation of ‘www’ to another server, if there is perhaps a CNAME for it, if there is a wildcard ‘*.powerdns.com’ record etc. DNSSEC brings further questions, should we do DNSSEC processing, and if so, are there keys we need to sign with?
Because of all this complication, and because back in 2000 we already predicted there would be many many backends, we decided to keep the ‘DNS logic’ central, where we would implement it once and leave the backends to being providers of data, pure and simple. It might have been better if we called the backends ‘DNS Data stores’ perhaps. But alas, we missed that chance.
So now that we’ve described how it doesn’t work, let’s check out the present day reality:
Packets come in from the Internet and get processed by our PacketHandler class. This class has all the logic on best zone selection, CNAMEs, wildcards, delegations, DNSSEC metadata etc. And to figure this all out, it sends many questions to the UeberBackend. The UeberBackend is subsequently responsible for distributing the queries over the multiple possible configured backends. In addition, it hosts a cache which optionally remembers answers (or lack thereof) a backend provided previously.
The best way to understand this procedure is that the PacketHandler turns DNS packets into data backend queries. This also means that backends should do no thinking. Just answer the question, with data or none. The PacketHandler can send many kinds of questions depending on the nature of your zone. For example, it may ask about SOA records, even for zones you do not host in your backend. This is because when a question comes in for ‘www.something.com’, PowerDNS must go hunt for a backend with relevant data.
As a further example of how things work, if PowerDNS asks a backend for ‘www.powerdns.com’, it can answer with a CNAME to ‘webserver1.cloudprovider.com’. PowerDNS itself then will attempt to follow the CNAME chain and check if there is data for the ‘cloudprovider.com’ zone. The backend does not need to think about this!
Why does my backend get ANY queries when no such queries are sent to the nameserver?
In addition, as a speedup, PowerDNS may ask ANY questions, which allow it to see if there is a CNAME for the DNS query name, and if there is no CNAME, get the right answer from the same question. This answers questions 1 and 3 from the list above.
How do I generate an NXDOMAIN answer from my backend?
Answering question 2, how to generate an NXDOMAIN from my backend also becomes easy: you need to convince PowerDNS that you do host the domain in question by delivering a SOA (aka Start of Authority) record when asked for your zone, and when you then get a question for ‘nosuchdomain.powerdns.com’, just return.. nothing. From this PowerDNS will conclude that 1) you host the zone 2) there is no record called ‘nosuchdomain.powerdns.com’. And this will lead to an NXDOMAIN.
So, the clarify even further, if you run a zone called ‘maik.de’, and PowerDNS receives a DNS query for ‘nosuchdomain.maik.de’, it will ask your backend if it knows about ‘nosuchdomain.maik.de’, and you should return no data. Next it will ask about ‘maik.de’, and if it asked for ANY or the SOA record, you should return the SOA record. From this PowerDNS will conclude that it should send out an NXDOMAIN.
Why does PowerDNS ignore the records my backend sends back to put in the packet?
Answering question 4, if a backend sends back records that PowerDNS did not ask for, these do indeed not end up in your packet. PowerDNS asked the backend if it had data for a certain name, and any replies not for that name are out of spec. Not only might PowerDNS ignore them, it could also decide your backend is not functioning correctly and drop the packet.
Why do I get way less/way more backend queries than DNS queries?
Answering questions 5 and 6: you may indeed get many more backend queries than DNS packets coming in. An individual DNS query may cause 4 or more backend queries. Each of these queries is necessary to figure out details about the domain. If your Pipe backend is flooded with questions it does not want to hear about, the ‘pipe-regex’ feature is available to quickly deny any knowledge about such domains.
You may also get a lot less questions, since the UberBackend has a cache that optionally stores previous answers from your backend. If this is not what you want, caches can be disabled, which may be useful if you want to provide fully dynamic answers.
Why does PowerDNS instantiate extra copies of my backend for AXFR?
Finally, the answer to question 7, why do new backends get spawned for zone transfers? An AXFR may last minutes, and since during those minutes a backend can do nothing else, a dedicated instance is created for each zone transfer (both incoming and outgoing).
We hope that this information has been helpful in clarifying what a PowerDNS backend is and isn’t.
Finally, if it turns out a PowerDNS backend is not actually what you want, you may be interested to hear about a currently undocumented feature in the PowerDNS Authoritative Server that we use for testing. This allows you to intercept queries sent to PowerDNS Authoritative Server, much like is possible (and documented) in the PowerDNS Recursor.
From the point of interception, you can mangle questions to your heart’s delight from Lua, and send back any answer you want. This feature will become documented and supported in PowerDNS 4.0, but for now, study the ‘lua-prequery-script’ configuration parameter. And if you have any questions, you can find us on the mailing lists or IRC.