I've looked around the web for a solution and have found numerous threads with different suggestions. Most of which I've found has been using LUA on the resolver to return records. Other posts suggest using GEO-IP or Pipe backends. All of the content I've read have used

I am curious to know if it is possible, via LUA to change the Forwarder based on the network range rather than using LUA to store zone information.

If I can get logic similar to the following to work I should be all set:

if sourceip comes from (,, {
     forwarder =;
     forwarder =;

I don't see any examples of LUA from pdns that demonstrate changing any settings within PDNS itself, and am curious if that is even possible.


Neither PowerDNS Server nor Recursor support the split-horizon setups in the way BIND does.

You can work around it by for example running Lua code in your recursor that directly provides the answers you want served for a specific subnet for example but as you already found out you cannot manipulate where queries will be forwarded to from Lua.

A relatively new addition to the PowerDNS family of code is a DNS loadbalancer which is programmable in Lua that does enable you to send queries do different nameservers based on just about anything that the DNS protocol allows for. See http://dnsdist.org/ and https://github.com/PowerDNS/pdns/blob/master/pdns/README-dnsdist.md . The Split Horizon example there splits recursive and non-recursive queries but you can just as well split it depending on the source address for example via the addPoolRule(netmask, pool) function.

Btw. the Lua people don't like it when you write it in all caps. See http://www.lua.org/about.html "Whats in a name" ;-)


This answer supports @ZaphodB's suggestion to use dnsdist. Here is a sample dnsdist.conf file that will do a split horizon setup, directing traffic either to Google's DNS servers or DNS servers in your local network depending on the target FQDN. The dq object is a DNS Question; your lua function can test against any property of that object.

-- bind to port 53 (default) on local machine.
-- setLocal clears existing, addLocal appends to existing

-- set up dns server pools

-- define split horizon policy
function splitHorizon(servers, dq)
if (string.find(dq.qname:toString(),'example.com.?$')) then
    print("local address")
    return leastOutstanding.policy(getPoolServers("local"), dq)
    print("other address")
    return leastOutstanding.policy(getPoolServers("google"), dq)

-- apply split horizon policy
setServerPolicyLua("splitHorizon", splitHorizon)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.