Saturday, January 23, 2010

DNS caching in Ubuntu

DNS caching in Ubuntu is really straightforward and can make a big difference to the speed of your general network activities, including browsing. Why? Well, on an average home network, a DNS request can take 40ms+, and given that (unless your on a webpage using direct IP addresses of course) pretty much every actual HTTP request, i.e. one that doesn't result in a local cache get, results in an initial DNS lookup. So, multiply every non-cached object on the webpage by your DNS lookup time, and you can have a big overhead.

Windows has had a local DNS cache for ages now, certainly since XP (and probably before that), but Linux distros have not, for various reasons. In fact, as far as I'm aware, only openSUSE has had a DNS cache enabled by default (the excellent ncsd).

There are many different DNS caching daemons available, but my favourite is dnsmasq. You can find more information about the advanced features of this software here, i.e. you can run it as a fully-fledged DNS and DHCP server for your network. Here I'll explain how to do simple DNS caching with it.

Firstly, install it (obviously). The repository for your distro will almost certainly have it, here I'm using Ubuntu 9.10, and the standard repository.

$ sudo apt-get install dnsmasq

Once it's installed, modify the /etc/dnsmasq.conf, and specify the listening IP address. Here, we're obviously going to use the local host address, so uncomment the following line :

listen-address=127.0.0.1

Now, you need to modify your DHCP configuration to use the local DNS cache first, if there isn't one, then fall back on your main DNS server. So,

$ sudo vi /etc/dhcp3/dhclient.conf

include the "prepend domain-name-servers 127.0.0.1" line

Note, that "prepend" puts the dns server ABOVE everything else, so ensure that the prepend statement above is LAST in the list.

The following is my setup, note I use OpenDNS, hence the IPs 208.67.222.222 and 208.67.220.220.

prepend domain-name-servers 208.67.222.222;
prepend domain-name-servers 208.67.220.220;
prepend domain-name-servers 127.0.0.1;

Now, when you DHCP lease expires the order of DNS servers should be 127.0.0.1 and then your existing DNS setup.

If you don't want to wait until your DHCP lease expires, you need to manually modify the /etc/resolv.conf file (which gets overwritten when the lease expires) :

$ sudo vi /etc/resolv.conf

And add

nameserver 127.0.0.1

to the top of the nameserver lists already in there.

Once this is done, restart your dnsmasq daemon, i.e.

$ sudo /etc/init.d/dnsmasq restart

So, how can you test that all this has had a positive effect? Well, you use the wonderful
dig command. Here's the example from my local machine :

$ dig chaddersblog.blogspot.com

; <<>> DiG 9.6.1-P2 <<>> chaddersblog.blogspot.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23451
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;chaddersblog.blogspot.com. IN A

;; ANSWER SECTION:
chaddersblog.blogspot.com. 2886 IN CNAME blogspot.l.google.com.
blogspot.l.google.com. 294 IN A 216.239.59.191

;; Query time: 31 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)

;; WHEN: Sat Jan 23 10:33:56 2010
;; MSG SIZE rcvd: 91

$ dig chaddersblog.blogspot.com

; <<>> DiG 9.6.1-P2 <<>> chaddersblog.blogspot.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27521
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;chaddersblog.blogspot.com. IN A

;; ANSWER SECTION:
chaddersblog.blogspot.com. 2884 IN CNAME blogspot.l.google.com.
blogspot.l.google.com. 292 IN A 216.239.59.191

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)

;; WHEN: Sat Jan 23 10:33:58 2010
;; MSG SIZE rcvd: 94

You can see from the bold sections that the first time I ran the command, the "Query time" was 31 msec (because it didn't have the DNS entry for that address), but the second time it did, so the Query time was instantaneous.

No comments: