3 min read

Implementing BIND Views with PowerDNS

Implementing BIND Views with PowerDNS

"Views" is a controversial feature of the BIND DNS software. Holy wars have been fought debating the merits and pitfalls of views. This article is not to praise views, but to bury them. I mean, to help with achieving the same results in PowerDNS.

Some people like views, and have built their existing DNS infrastructure to rely on views. Most of the time, they use views to present "an alternative DNS reality" to some network users. Image your servers have both internal and external ip-addresses, and you want your local users to use the internal ips, and your external users the public ip.

When you consider migrating your DNS infrastructure to PowerDNS - and as a Certified PowerDNS Consultant I would recommend you do consider migrating — you need to recreate the same functionality in the pdns ecosystem.

There are multiple ways of achieving this result, but in this blog post, I'll describe the method that usually makes the most sense. It involves two pdns instances and a dnsdist loadbalancer.

Our scenario involves a zone mycompany.tld. We want to configure our "split-horizon" DNS to serve the internal zone-file zone-internal.db to all requests from clients in the 10.10.10.0/24 subnet, and use the public zone zone-public.db to all other clients.

PowerDNS instances

Instead of fiddling with LUA in the auth server, we start two instances of the PowerDNS Authoritative server. Both instances are configured to be authoritative for the mycompany.tld zone. The first one is running on port 1053 and is configured to use the internal zonefile. The second one is running on port 2053 and will use the public zonefile. Both PowerDNS instances use the bind backend to make this demo easier. For production environments, I'd recommend you take a look at the brand new and screaming-fast LMDB backend or one of the SQL backends if you want to use database-level replication.

/etc/powerdns-internal/pdns.conf

setgid=pdns
setuid=pdns

launch=bind

bind-config=/etc/powerdns-internal/named.conf

local-port=1053
socket-dir=/var/run/powerdns-internal

/etc/powerdns-external/pdns.conf

setgid=pdns
setuid=pdns

launch=bind

bind-config=/etc/powerdns-external/named.conf

local-port=2053
socket-dir=/var/run/powerdns-external

/etc/powerdns-external/named.conf

The bind-config file resembles a traditional BIND config file snippet, as shown below.

zone "mycompany.tld" {
    file "/var/lib/powerdns/zone-external.db";
    type master;
};

The "internal" instance has the exact named.conf file, but references our internal zone file.

dnsdist loadbalancer

In front of both servers, we're running a dnsdist instance. dnsdist is a software DNS loadbalancer and attack filtering tool. We'll use the load balancing features in this example to send all requests from the internal subnet to the "internal" pdns instance, and all other requests to the "public" instance.

/etc/dnsdist/dnsdist.conf

setLocal('0.0.0.0')
setACL('0.0.0.0/0')

newServer({address="127.0.0.1:1053", pool="internal"})
newServer({address="127.0.0.1:2053", pool="external"})

addAction({"10.10.10.0/24"}, PoolAction("internal"))
addAction(AllRule(),PoolAction("external"))

As you can see, our dnsdist configuration is very minimal. We listen on all ip-addresses (port 53 by default) and allow all ips to query our setup.

We then define two pools of servers, an internal one and an external one. The last two lines are where the "magic" happens. All requests from clients in our local 10.10.10.0/24 subnet are sent to the internal pool (and thus to the pdns instance running on port 1053), all other requests are routed to the external pool and are served by the pdns instance running on port 2053.

Conclusion

So while PowerDNS doesn't implement views natively, and probably never will, it's fairly easy to use dnsdist to achieve the same result. Do you need advice on your DNS migration? Don't hesitate to contact me to discuss your options!