Have you ever wanted to serve different DNS records out based on the location of the originating request?
Using the GeoDNS Bind patch we can have example.com resolve to a server in the US only if the requesting IP address loading the page is based in the US, and then have all other requests forward onto a server based in another country. You will be able to point a request for a domain from any country code to specified DNS records with this method.
This can be beneficial for many reasons, it will allow faster website page load times in different countries due to all content being served by the nearest server. It also allows you to run up different websites for the same domain in different countries as these will be running on different servers.
In this example we will be compiling Bind from source on our test server (CentOS 6.3) which is acting as the name server, that is it is used to serve out DNS.
Compiling Bind with the GeoDNS patch
Download and install Maxmind’s GeoIP C API – I’m using current latest version 1.4.8.
wget http://geolite.maxmind.com/download/geoip/api/c/GeoIP-1.4.8.tar.gz tar xf GeoIP-1.4.8.tar.gz cd GeoIP-1.4.8 ./configure --prefix=/usr/local/geoip ... checking zlib.h usability... no checking zlib.h presence... no checking for zlib.h... no configure: error: Zlib header (zlib.h) not found. Tor requires zlib to build. You may need to install a zlib development package.
To fix this error we just need to install the zlib development package (zlib1g-dev on Debian).
yum install zlib-devel.x86_64 ./configure --prefix=/usr/local/geoip make make install
Download the GeoDNS patch for Bind.
cd .. wget http://www.caraytech.com/geodns/bind-9.4.1-geodns-patch.tar.gz tar xf bind-9.4.1-geodns-patch.tar.gz
Next download Bind.
Note that I am using this version of Bind (9.4.1-P1) because this is the version the current patch is for. I have not tested the patch with newer versions of Bind however it is believed to still work, please test this however before applying into production environments.
wget http://ftp.isc.org/isc/bind9/9.4.1-P1/bind-9.4.1-P1.tar.gz tar xf bind-9.4.1-P1.tar.gz
Now we will be using the Patch command, this was not installed for me initially so it was installed using yum.
patch -p0 < bind-9.4.1-geodns-patch/patch.diff bash: patch: command not found yum install patch ... patch -p0 < bind-9.4.1-geodns-patch/patch.diff ... patching file bind-9.4.1-P1/lib/dns/acl.c patching file bind-9.4.1-P1/lib/dns/include/dns/acl.h patching file bind-9.4.1-P1/lib/isccfg/aclconf.c
Now we will compile Bind specifying our GeoIP installation in /usr/local/geoip/ from earlier.
cd bind-9.4.1-P1 CFLAGS="-I/usr/local/geoip/include" LDFLAGS="-L/usr/local/geoip/lib -lGeoIP" ./configure --prefix=/usr/local/bind ... checking for C compiler default output file name... a.out ./a.out: error while loading shared libraries: libGeoIP.so.1: cannot open shared object file: No such file or directory See `config.log' for more details.
This only happened with the CentOS 6.3 test I was running, and did not happen with Debian 6 - the fix is simple.
nano /etc/ld.so.conf Add "/usr/local/geoip/lib/" into file and save. ldconfig
Trying again should now succeed.
CFLAGS="-I/usr/local/geoip/include" LDFLAGS="-L/usr/local/geoip/lib -lGeoIP" ./configure --prefix=/usr/local/bind make make install
Configuration
Now that Bind is compiled and installed with the GeoDNS patch we just need to configure our DNS to how ever we want.
This is done through the named.conf file, I've created this file within /usr/local/bind/etc/ and it contains the following:
include "/etc/rndc.key"; controls { inet 127.0.0.1 allow { localhost; } keys { "rndc-key"; }; }; options { directory "/var/named"; // the default pid-file "/var/run/named/named.pid"; dump-file "data/cache_dump.db"; statistics-file "data/named_stats.txt"; allow-transfer {"none";}; } logging { channel default_debug { file "data/named.run"; severity dynamic; }; };
In this example, the included file "/etc/rndc.key" exists and contains the following.
key "rndc-key" { algorithm hmac-md5; secret "RSQjVF5KKE0pI0VNVA=="; };
The secret is a simple base 64 string.
Now under this we define our views. In this example we will be sending all North American users who request example.com to the site hosted at 1.1.1.1, while sending the rest of the world to 2.2.2.2.
view "north_america" { match-clients { country_US; country_CA; country_MX; }; recursion no; zone "example.com" { type master; file "/var/named/example-us.com.db"; }; }; view "other" { match-clients { any; }; recursion no; zone "private-software.com" { type master; file "/var/named/example.com.db"; }; };
So our named.conf file is used to specify which .db zone file should be used, in this example we have two files for example.com that give out different DNS as follows.
/var/named/example-us.com.db
; Zone file for example.com $TTL 14400 example.com. 86400 IN SOA ns1.example.com. admin.example.com. ( 2012080500 ;Serial Number 86400 ;refresh 7200 ;retry 3600000 ;expire 86400 ) example.com. 300 IN A 1.1.1.1
/var/named/example.com.db
; Zone file for example.com $TTL 14400 example.com. 86400 IN SOA ns1.example.com. admin.example.com. ( 2012080500 ;Serial Number 86400 ;refresh 7200 ;retry 3600000 ;expire 86400 ) example.com. 300 IN A 2.2.2.2
Once the changes are all in place named can be started.
cd /usr/local/bind/sbin/ ./named
You will want to confirm that it has started with no errors, as problems with named.conf can cause this to fail. A good place to look for errors is /var/log/messages. Alternatively run netstat -antp and see if the server is listening on port 53 for DNS.
Summary
With this patch installed you will now be able to create different zone files for users requesting DNS from the server running Bind - the name server. These requests will be served different DNS based on the country the IP address originates from which can allow you to do a lot of really cool things.
Hi Jarrod,
Tried to follow your instructions, they were very accurate. well done!
The thing is that now, in the bind configuration, I get some errors about some files missing (I checked, and the /var/named folder for instance indeed wasn’t created, as well as the /etc/rndc.key file.
The process went smooth on Centos 6.4, what am I missing?
Many thanks,
Isaac.
Hi,
can you help me..
i test it at debian 6 but i cannot see listening port 53?
during process compailer I do not find error at all
root@angga:/usr/local/bind/sbin# ./named-checkconf
root@angga:/usr/local/bind/sbin# ./named
root@angga:/usr/local/bind/sbin# netstat -npl | grep 53
root@angga:/usr/local/bind/sbin# cat /etc/issue
Debian GNU/Linux 6.0 \n \l
thanks.
Did you start named? Do you get any errors logged when you attempt to start it?
Hi, it’s a great tutorial.
Anyway, I’m a new guy in this stuff. Can you tell me how we can use your system for multiple domains ?
So I want to use this DNS system for about 5 or 7 domains.
@angga: for debian you do not have to use this howto as debian bind package is already patched …
hth
regards tcpdump
No start named?
It was started in this case with these commands as mentioned in the post:
cd /usr/local/bind/sbin/
./named