Split DNS via PowerDNS Recursor

After fumbling around for some time on my Fedora 20, I seem to have made it work. I haven't found a full how-to anywhere, so a short writeup for a minimal setup:



We want to resolve webserver.dyndns.org to access a web service on it, both from the Internet and the LAN.



From the Internet

Machine a on the Internet resolves webserver.dyndns.org to the IP address IPisp. Behing IPisp is a router with NAT, which port-forwards port 80 to LAN IP IPx, thus making a web service available on the Internet.

This is naturally done by registering IP address IPisp at the authoritative nameserver for domain dyndns.org, which, in the case of a service like DynDns, is done using ddclient running on the router or somewhere in the LAN, and thus of no further interest here.

From the LAN

Machine b on the LAN resolves webserver.dyndns.org to the IP address IPx, so that the web service becomes available on the LAN directly. Additionally, assuming all the machines on the LAN are named along the lines of bar.localdomain, the name webserver.localdomain should also resolve to IPx. We also want to have reverse lookup for good measure, resolving IPx to webserver.dyndns.orginside the LAN (on the Internet, IPx resolves of course to nothing and IPisp resolves to some arbitrary string generated by the ISP.)

We assume pdns-recursor is running on a separate machine with IP IPdns, but we could also have it running on the webserver (on the same IP address as IPx or on an alias), or have only a single machine on the LAN.

Machine "b" may be configured statically or dynamically via DHCP; see dhclient and dnsmasqand possibly avahi. NetworkManager also enters here because it may rewrite /etc/resolv.conf; for now, assume static configuration.

Also, assume:

IPx = 192.168.1.1
IPdns = 192.168.1.2
IPbar = 192.168.1.3

Then:

/etc/resolv.conf on any machine:

nameserver 192.168.1.2
domain localdomain

Configuration for pdns-recursor:

/etc/pdns-recursor/recursor.conf basically reduces to:

setuid=pdns-recursor
setgid=pdns-recursor
allow-from=127.0.0.0/8, 192.168.1.0/8, ::1/128, fe80::/10
auth-zones=webserver.dyndns.org=/etc/pdns-recursor/[webserver.dyndns.org].zone, localdomain=/etc/pdns-recursor/[localdomain].zone, 168.192.in-addr.arpa=/etc/pdns-recursor/[168.192.in-addr.arpa].zone
local-address=192.168.1.2

The above references very much cut-down zone files (their actual names are unimportant):

In /etc/pdns-recursor/[168.192.in-addr.arpa].zone (note the lack of a dot at the end of the record name - it is a relative name not an absolute one: 1.1 means 1.1.168.192.in-addr.arpa). This works with or without the "IN".

1.1   IN   PTR     webserver.dyndns.org.
2.1   IN   PTR     dns.localdomain.
3.1   IN   PTR     b.localdomain.

In /etc/pdns-recursor/[webserver.dyndns.org].zone (note the dot at the end of the record name - it is an absolute name not a relative one)

webserver.dyndns.org.  IN  A  192.168.1.1

In /etc/pdns-recursor/[localdomain].zone

webserver    IN  A  192.168.1.1
dns          IN  A  192.168.1.2
b            IN  A  192.168.1.3

After a restart of pdns-recursor, on can test using dig by running these commands:

PDNS=192.168.1.2

# Test unknwon domain resolution and webserver resolution    
dig @$PDNS www.cnn.com | grep -A1 ";; ANSWER SECTION:"                  
dig @$PDNS webserver.dyndns.org | grep -A1 ";; ANSWER SECTION:"

# Test responses for localdomain
dig @$PDNS unknown.localdomain | grep -A1 ";; ANSWER SECTION:"
dig @$PDNS webserver.localdomain | grep -A1 ";; ANSWER SECTION:"
dig @$PDNS b.localdomain | grep -A1 ";; ANSWER SECTION:"
dig @$PDNS dns.localdomain A | grep -A1 ";; ANSWER SECTION:"

# Test responses for localdomain if the domain is omitted
dig +search @$PDNS webserver | grep -A1 ";; ANSWER SECTION:"

# Test reverse resolution
dig @$PDNS -x 192.168.1.1 | grep -A1 ";; ANSWER SECTION:"
dig @$PDNS -x 192.168.1.2 | grep -A1 ";; ANSWER SECTION:"
dig @$PDNS -x 192.168.1.3 | grep -A1 ";; ANSWER SECTION:"
dig @$PDNS -x 192.168.1.4 | grep -A1 ";; ANSWER SECTION:"