DNS: how to get local server to superimpose results over authoritative server?
I've got a domain for which the DNS I control, and is hosted on the internet. I also have a NAT'd internal network (192.168.0.0/24) which has internet access, and which I also control. On this internal network, I also have a DNS resolver. DNS software on both is PowerDNS.
What I want to be able to do is for the DNS resolver on the internal network to be able to add/change records of queries and results that come down from the authoritative server. For example, the authoritative server might have a single record for animal.example.com:
animal.example.com. IN AAAA 2001:140:283::1
However, I'd like it so that when internal clients do a dns lookup for animal.example.com, they might get back the following:
animal.example.com. IN AAAA 2001:140:283::1
animal.example.com. IN A 192.168.0.2
Obviously, I could set up the internal DNS server to pretend to be authoritative for example.com, but that would require a fair bit of effort to keep the main DNS server and the internal DNS server in sync for the records which are the same between both. If the internal DNS server could somehow be made a slave of the main DNS server, but also have the provision to add its own results in, that would be ideal.
Is this possible?
Solution 1:
Actually if i had to do it i would use a Lua Script with the recursor that mangles with the data on postresolve.
Hoever i really do recommend something different: Simply use a seperate authoritative Zone like internal.example.com where you AXFR example.com from the authoritative Servers and simply append your local RFC1918 data.
This way you can still debug the authoritative Zone like it is on the internet from your LAN and use the internal data.
About PowerDNS Recursor Lua Scripting: http://doc.powerdns.com/recursor-scripting.html
Solution 2:
What I think you want is a split-horizon DNS setup, however PowerDNS doesn't directly support such (unlike Bind or DJBDNS). The official response about it from the author is here: http://mailman.powerdns.com/pipermail/pdns-users/2006-September/003779.html
I've never found split-horizon DNS to be particularly confusing, myself, especially if files are laid out clearly in the file system, e.g. ./master-interal/domain.com ./master-external/domain.com
The only option they're suggesting is to have two different instances of PowerDNS running on a server listening on different ports. I guess you would then leverage iptables to redirect traffic to port 53 to whichever instance is relevant.
Solution 3:
I strongly recommend that you don't go down this path as it is extremely confusing, complex, and difficult to manage. Instead, you should set up a separate internal domain like inside.example.com
. Then, if your outside dns server is also on your inside network, you should set it up to be authoritative for both domains. However if your external dns server isn't on your internal network, you should set up your inside dns server to be authoritative for inside.example.com. Then your inside dns server should forward all other requests to the outside dns server.
I realize the downside of this is you have to change the domain on all your inside machines, but doing that up-front work now will save you a lot of confusion later on.
Solution 4:
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.org
inside 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 dnsmasq
and 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:"