Cache your DNS requests using Bind

Posted on 15.03.2009 by Kim N. Lesmer.
This tutorial describes how you can speed up DNS requests using BIND as a local cache.

Before a mail server such as Postfix can transport a message to a remote destination, it must locate that destination. On the Internet, you find remote resources with the Domain Name System. A nameserver returns the IP address of a domain name, and conversely the domain name that corresponds to an IP address.

A well performing DNS is critical to MTA (Mail Transfer Agent) performance. The sooner the mail server can resolve a target IP address, the sooner it can start to communicate with the remote mail server.

Poor hostname lookup performance can become a major problem on large mail servers. If your server runs into problems, a cache can help, but you must be aware that anti-spam measures can increase the number of DNS queries that your mail server performs.

On Debian Squeeze there are several different packages you can use for caching DNS requests - including BIND, djbdns, dnsmasq and pdnsd.

I prefer BIND and BIND is the most commonly used DNS server on the Internet. On Debian you can install BIND using the following command:

# apt-get install bind9

In this example I will setup BIND to resolve DNS requests, but at the same time, I will make sure that if BIND for some reason becomes unavailable the system will still make use of the DNS servers from your ISP.

In /etc/resolv.conf you need the IP addresses of the DNS servers available to you. It can be the DNS servers provided by your ISP, or it can be DNS servers provided by OpenDNS, or both. In this example we are using the DNS servers from OpenDNS.

On Debian you don't have to worry about the resolv.conf getting renewed automatically unless you have installed the program resolvconf (please notice the filename is almost identical).

With the DNS servers from OpenDNS /etc/resolv.conf looks like this:

nameserver 208.67.222.222
nameserver 208.67.220.220

With this setup DNS queries will be performed against these two DNS servers. Now, we need to make sure that all DNS request are performed against the BIND server on our local machine. To do this just change /etc/resolv.conf into the following:

nameserver 127.0.0.1

Next you need to setup BIND. Edit the /etc/bind/named.conf.default-zones file and uncomment the following lines (if they are commented out):

zone "." {
type hint;
file "/etc/BIND/db.root";
};

Then you need to configure BIND to forward DNS requests to your DNS servers (in this case the ones from OpenDNS). Edit the file /etc/bind/named.conf.options and add the following to the "forwarders" section:

forwarders {
208.67.220.220;
208.67.222.222;
};

At this point you need to restart BIND, on Debian you can do that the following way:

# /etc/init.d/bind9 restart

The first time BIND gets a DNS request it will look it up at the DNS servers from OpenDNS, it will then cache the result and the next time it gets the same request it will provide the results from the cache speeding up the process highly.

You can test your local DNS query with the dig utility (it is a part of the dnsutils package.):

$ dig yahoo.com

In my case the query responds time was:

;; Query time: 33 msec

Now lets try that again:

$ dig yahoo.com

Lets check out the second result:

;; Query time: 1 msec

As the example clearly shows my DNS query has been cached and the second attempt was resolved much faster.

If you have any comments or corrections feel free to email them to me.