Thursday 27 January 2011

HOWTO: Caching Authoritative Nameserver

OK, so you have built yourself a Linux Router and now you want to add DNS support for extra goodness.

Here's what to do.

I'll be working on Debian 6.01 "squeeze" but any Debian based distro should be fine. I've also tested on Ubuntu 10.04 without problems. I am using 10.1.1.0/24 as my local network and tuxnetworks.net as my local domain. Where you see references in italics to these you should change them to suit your own network.

First we will log in as root

As root, install Bind v9 from the standard repositories;

apt-get install bind9

Now we need to tell Bind to listen for queries on our IPv4 LAN.

Open this file for editing;

vi /etc/bind/named.conf.options

add the following lines inside the "options { };" section ;

listen-on { any; };
allow-recursion { 127.0.0.1; 10.1.1.0/24; };


Note:
"Recursion" is a fancy term for "which clients can query our server". Basically, you want to enter the local loop interface (127.0.0.1) and the subnet of your LAN. You can add any other hosts or subnets as required. Also, if you are not intending to use IPv6 you can comment or remove the "listen-on-v6" line out if you like.

Now we will create a zone file for our local zone;

Note:
I prefer to keep the configuration details for zones in separate files so I am going to create a file in which I will define the details for the "tuxnetworks.net" zone. If you don't want to do this just add the following code section to named.conf.options

vi /etc/bind/named.conf.tuxnetworks-net

Adjust the following code to suit your own network and then add it to the zone file;
# This is the zone declaration for our local zone.
zone "tuxnetworks.net" {
type master;
file "/etc/bind/db.tuxnetworks.net";
};

# This is the zone declaration for reverse DNS
zone "1.1.10.in-addr.arpa" {
type master;
file "/etc/bind/db.1.1.10.in-addr.arpa";
};

Now that we have created our zone declaration file, we have to tell bind to load this file when it starts. We do this by adding an "include" line to named.conf

Edit named.conf;

vi /etc/bind/named.conf

Append this line to the end;

include "/etc/bind/named.conf.tuxnetworks-net";

Now we need to make a zone file for our domain. This is where we define the names and attributes of our zone.

Create a zone file;

vi /etc/bind/db.tuxnetworks.net

Modify these details and save them to your zone file;
$TTL    3600
tuxnetworks.net. IN SOA ns.tuxnetworks.net. jupiter.tuxnetworks.net. (
2011051701 ; Serial
86400 ; Refresh
7200 ; Retry
3600000 ; Expire
172800 ) ; Minimum TTL

; DNS Servers
tuxnetworks.net. IN NS ns.tuxnetworks.net.

tuxnetworks.net. IN MX 10 mail.tuxnetworks.net.

@ IN A 10.1.1.1
ns IN A 10.1.1.1
www IN A 10.1.1.1
mail IN A 10.1.1.1
jupiter IN A 10.1.1.1

Note: Take note that several names in this file have a trailing period (fullstop). Make sure that your file matches the format of this one exactly, only changing the names and IP addresses, but where present keeping the periods intact.

We also need to make a reverse zone file. Create a new file;

vi /etc/bind/db.1.1.10.in-addr.arpa

Add this code (modified to suit your network of course);
;
; BIND reverse data file for local network
;
$TTL 604800
@ IN SOA jupiter. ns. (
1 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS ns.
1 IN PTR ns.

Finally, there is one thing more to do if we are going to be good netizens and that is to ensure that we play by the rules according to RFC 1918

After running your server for a while you might take a look at /var/log/syslog and notice lots of bind related errors saying something like "RFC 1918 response from Internet for . . . .".

If you do then this means that your server is not playing nice with the root servers and is forwarding on requests for private IP ranges. That is not something we want to do.

To fix it edit your named.conf file;

vi /etc/bind/named.conf

Add the following line to the end;

include "/etc/bind/zones.rfc1918";

This stops any requests for private IP address's (192.168 etc) from being passed on to the Internet root servers. One wonders why Bind isn't configured like this by default . . .

And that's it. Of course we need to restart bind before our changes take effect;

service bind9 restart

Also, before we can query our new DNS server, we need to configure the client to look to this server for name resolution.

To do that, edit your resolv.conf file;

vi /etc/resolv.conf

Remove any exiting lines and add these (modified to suit your own network of course);

nameserver 10.1.1.1
domain tuxnetworks.net


Optional:
If you don't wish to query against the Internet root servers, edit your named.conf.options file and configure a forwarder or two.

vi ./etc/bind/named.conf.options

Uncomment the "forwarders {" section and replace the 0.0.0.0 with the ip address of the upstream DNS server(s) you would like to use.
  forwarders {
208.67.222.222;
208.67.220.220;
};

Now let's do some tests to see if it is all good with our new server;

Let's dig our domain;

dig tuxnetworks.net

; <<>> DiG 9.7.0-P1 <<>> tuxnetworks.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28277
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;tuxnetworks.net. IN A

;; ANSWER SECTION:
tuxnetworks.net. 3600 IN A 10.1.1.1

;; AUTHORITY SECTION:
tuxnetworks.net. 3600 IN NS ns.tuxnetworks.net.

;; ADDITIONAL SECTION:
ns.tuxnetworks.net. 3600 IN A 10.1.1.1

;; Query time: 1 msec
;; SERVER: 10.1.1.1#53(10.1.1.1)
;; WHEN: Tue May 17 12:09:08 2011
;; MSG SIZE rcvd: 82


We can see from this that we received an answer (ANSWER: 1) along with some other details about our domain. Also note the AUTHORITY: 1
which lets us know that this server is acting as the authority for the domain.

We can also do some ping tests.

Do a test ping to an internal name (we don't need to provide the domain name because we used the "domain" directive in resolv.conf which will automatically append our domain to any query that doesn't include a domain. Neat!;

ping -c 4 www
PING www.tuxnetworks.net (10.1.1.1) 56(84) bytes of data.
64 bytes from jupiter.tuxnetworks.com (10.1.1.1): icmp_seq=1 ttl=64 time=0.130 ms
64 bytes from jupiter.tuxnetworks.com (10.1.1.1): icmp_seq=2 ttl=64 time=0.089 ms
64 bytes from jupiter.tuxnetworks.com (10.1.1.1): icmp_seq=3 ttl=64 time=0.090 ms
64 bytes from jupiter.tuxnetworks.com (10.1.1.1): icmp_seq=4 ttl=64 time=0.091 ms

--- www.tuxnetworks.net ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2998ms
rtt min/avg/max/mdev = 0.089/0.100/0.130/0.017 ms


Our Bind server will forward any requests that it isn't an authority for out to the Internets DNS root servers which means we no longer need to rely on our dodgy ISP's DNS servers where they are quite likely engaged in DNS Hijacking shenaningans.

Do a test ping to the outside world;

ping -c 4 www.google.com
PING www.l.google.com (74.125.237.84) 56(84) bytes of data.
64 bytes from 74.125.237.84: icmp_seq=1 ttl=57 time=57 ms
64 bytes from 74.125.237.84: icmp_seq=2 ttl=57 time=40.3 ms
64 bytes from 74.125.237.84: icmp_seq=3 ttl=57 time=59 ms
64 bytes from 74.125.237.84: icmp_seq=4 ttl=57 time=45 ms

--- www.l.google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3002ms
rtt min/avg/max/mdev = 90.384/137.973/159.187/28.004 ms


So, our DNS server is all up and running, it is acting as authority for tuxnetworks.net and passing any other requests out to the Internet. It is also caching any queries to reduce on net traffic!

OK, we are all done now, grab yourself a beverage and relax!

Now that you have built yourself a DNS server, why not build a second one and configure it as a SLAVE?