UPDATE 29/03: double checked the config I was using, and the default PowerDNS config, and apparently there are some config items that need to be changed, query-cache-ttl and cache-ttl. I’ve added them to the sample config.
PowerDNS has an interesting backend called ‘geo’, which allows to send different responses based on the IP address of the ‘user’ .
First of all, let’s install PowerDNS with the geo backend, The information below assumes you’re using Debian as distro, and already have a working DNS infrastructure.
$ sudo apt-get install pdns-server pdns-backend-geo rsync
open /etc/pdns/pdns.d/pdns.local and add the following lines, and replace the hostnames,
launch=geo geo-zone=iso.geek.be geo-soa-values=dns1.geek.be,email@example.com geo-ns-records=dns1.geek.be,dns2.geek.be wildcards=no geo-ttl=60 geo-ns-ttl=3600 cache-ttl=0 query-cache-ttl=0 geo-ip-map-zonefile=/etc/powerdns/zz.countries.nerd.dk.rbldnsd geo-maps=/etc/powerdns/geo-maps
The nice people at Mermaid Consulting provide a file with all IP-to-ISO mappings that can directly be used by PowerDNS. It uses the country value from the WHOIS records from all IP registries.
$ rsync -q rsync://countries-ns.mdc.dk/zone/zz.countries.nerd.dk.rbldnsd /etc/powerdns/
Local copy of the file: zz.countries.nerd.dk.rbldnsd
Next we need to prepare the ISO-to-DNS file, it uses the ISO 3166 numeric notation.
Create a new file in /etc/powerdns/geo-maps, e.g. iso.geek.be. You can either fill it manually or use this prepared file. The latter has been prepared by using this small PHP script with this ISO listing (local copy).
$ sudo /etc/init.d/pdns restart
The last step is adding a NS record in your existing master PowerDNS server, e.g. iso.geek.be NS dns3.geek.be, and then an A record for dns3.geek.be pointing to your PowerDNS Geo server.
Let’s see if it works,
$ dig iso.geek.be ; <<<< DiG 9.8.1-P1 <<>> iso.geek.be ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 3471 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0 ;; QUESTION SECTION: ;iso.geek.be. IN A ;; ANSWER SECTION: iso.geek.be. 60 IN CNAME be.iso.geek.be.
As you can see, it works.
- add CNAME’s to iso.geek.be (e.g. cdn.geek.be)
- change the country based mappings in the iso.geek.be file to a region based mapping (e.g. 56 eu, 528 eu, 826 eu, etc). And then add just 1 record for each region, instead of per country.
- another way, more flexible but more work, is to add CNAME’s for each country to the same region (be.iso CNAME eu.iso.geek.be, nl.iso CNAME eu.iso.geek.be)
Note: The IP used to check the mapping is the IP address of the user’s DNS server, in most cases this is the IP address of the DNS server of the user’s ISP. However, if you have configured your DNS servers to e.g. Google, it will provide the ‘US’ mapping.