For those of you unfamiliar, NXDOMAIN is a DNS query response for non-existent domain. An example would be if you start typing google.com, but sneeze halfway through, and end up going to gegooele.com. That domain doesn’t exist, and you will ultimately receive an NXDOMAIN response from your upstream DNS server instead of an A record with the IP of the domain.
These days, a lot of ISPs have been doing NXDOMAIN redirection. Instead of handing back the NXDOMAIN response, they will intercept it and send you back an A record with an IP of one of their web servers (lets say 1.2.3.4 as an example). Your machine will ultimately think that gegooele.com has the IP 1.2.3.4, connect to that IP, and do a GET request with the HTTP host header of gegooele.com. The ISP’s web server, which specifically handles NXDOMAIN “redirected” HTTP requests, will then take that host header, pass it through some type of dynamic script, and display a nice custom error page with possible corrections, advertisements, etc.
Now, here’s where PowerDNS comes in: there are companies out there whose specialty is to sell DNS appliances and software solutions, solely for the purpose of doing NXDOMAIN redirection. However, if you are in the market for doing something like this (which is a whole separate discussion altogether, since there are strong opinions about this subject), you can save yourself a chunk of change by instead using PowerDNS (pdns-recursor, to be exact) with built-in Lua scripting. PowerDNS is open source, free, awesome.
We’re going to skip the build/compile details for now, and assume you have the latest PowerDNS recursor installed, and that Lua scripting has been compiled in. Chances are, it has. If not, check out http://www.powerdns.com and download the latest source. Once it’s installed, you just need to write a Lua script to modify DNS results, configure your recursor to use the script, and start up pdns-recursor. Let’s get to it.
First, you need to define a Lua script to handle DNS responses. Currently, Lua will only handle two types of responses: nxdomain, and preresolve. Preresolve is a response to give before any resolution has taken place. This is to basically hijack requests with a static response.
To define, we’ll add this line to our recursor.conf:
lua-dns-script=/opt/pdns/bin/nxdomain.lua
Now, let’s write our script. At it’s most basic level, it’s really easy:
function nxdomain (ip,domain,query_type)
ips={}
if query_type ~= pdns.A then return -1, ret end
ips[1]={ query_type=pdns.A, content="1.2.3.4" }
ips[2]={ query_type=pdns.A, content="5.6.7.8" }
return 0, ips
end
This script will first make sure our NXDOMAIN response is the result of a request for an A record. As long as it is, we will build an A record response to return instead of an NXDOMAIN. Per this code, the client will ultimately receive an A rotor response with two records.
Now that our script has been written and added to our recursor.conf, let’s start up the recursor and try it out!
$ /opt/pdns/sbin/pdns_recursor –config-dir=/opt/pdns/etc
Assuming the script is loaded successfully, you will see the following from the startup output:
Nov 25 03:09:36 Loaded ‘lua’ script from ‘/opt/pdns/bin/nxdomain.lua’
Looks good. Now, let’s see what happens when we try to hit our non-existent gegooele.com:
$ host gegooele.com
gegooele.com has address 1.2.3.4
gegooele.com has address 5.6.7.8
And there we go! NXDOMAIN redirection without the need for a commercial solution. Of course, there are more things you can do [with the Lua script]. WIth the proper log level, you can have it log every time the handler is called. For example, you can add a simple print line:
print ("nxdomain handler received: ", ip, domain, query_type)
You can also have it make decisions based on incoming IP, hostname/domain, and query type. However, the point of this was just to show the basics with what you can do. For more Lua syntax, and PowerDNS capabilities with Lua, check out the Lua website and PowerDNS wiki. Enjoy!




Oh hey Chet,
i found your post by googling for my own latest one and thought you would want to know what i have been running for about a year now on the recursors i manage:
http://blog.zaphods.net/2009/12/09/powerdns-recursor-lua-scripting-examples/
and some more that i cannot reveal ofc, however i have never seen any performance impact from running a Lua script, it is just that fast. \o/
Stefan
I just tested, and Python does what you would expect. But of course it does, Python always does :p.