DNS is the first step made when you try to access a site / server over the internet. Sometimes, the delay to make a query can compromise system performance in both servers and desktops. Or eventually more than one program tries to query the same address and the system libraries have to do two queries, when only one was enough.
The solution presented here, configures a local DNS server to serve the system itself, improving network performance by caching solved addresses, reducing the initial connection delay. It is specially important for performance on mail servers. On the desktop side, web browsing will be a smoother experience, specially when you bandwidth is in full use by a download.
This text assumes that the reader is familiar with DNS engine enough to understand how it works.
BIND is a versatile DNS server that we will be using. Installing it should be easy on most distributions. Under Debian / Ubuntu you can just:
# apt-get install bind9
Most distributions will ship a working configuration that will query the root servers to solve addresses and "just work". Things will usually be better if we forward our queries to the ISP's DNS servers instead of bothering the root servers and country level DNS servers.
To to that, let's remove the root servers configuration. Locate your BIND configuration file. On Debian / Ubuntu, it will be /etc/bind/named.conf and comment the following lines:
zone "." {
type hint;
file "/etc/bind/db.root";
};
by adding // to the beginning, like this:
// zone "." {
// type hint;
// file "/etc/bind/db.root";
// };
Now let's configure BIND to forward our queries to the ISP's server. Locate the options section of the configuration (on Debian / Ubuntu, it will be at /etc/bind/named.conf.options) and add the following forwarders section:
options {
...
...
forwarders {
1.2.3.4; // your ISP's primary DNS address, adjust it!
5.6.7.8; // your ISP's secondary DNS address, adjust it!
};
...
...
};
Adjust the address to match your ISP's addresses.
Restart BIND for it to read the new configuration. On Debian / Ubuntu:
# /etc/init.d/bind9 stop # /etc/init.d/bind9 start
Check system's log file for error. On Debian / Ubuntu, try:
# grep named /var/log/daemon.log
You should get something like:
Jun 22 17:54:26 morpheus named[12065]: shutting down: flushing changes Jun 22 17:54:26 morpheus named[12065]: stopping command channel on 127.0.0.1#953 Jun 22 17:54:26 morpheus named[12065]: stopping command channel on ::1#953 Jun 22 17:54:26 morpheus named[12065]: no longer listening on ::#53 Jun 22 17:54:26 morpheus named[12065]: no longer listening on 127.0.0.1#53 Jun 22 17:54:26 morpheus named[12065]: no longer listening on 169.254.10.71#53 Jun 22 17:54:26 morpheus named[12065]: no longer listening on 192.168.1.101#53 Jun 22 17:54:26 morpheus named[12065]: exiting Jun 22 17:54:29 morpheus named[12204]: starting BIND 9.3.4 -u bind Jun 22 17:54:29 morpheus named[12204]: found 1 CPU, using 1 worker thread Jun 22 17:54:29 morpheus named[12204]: loading configuration from '/etc/bind/named.conf' Jun 22 17:54:29 morpheus named[12204]: listening on IPv6 interfaces, port 53 Jun 22 17:54:29 morpheus named[12204]: listening on IPv4 interface lo, 127.0.0.1#53 Jun 22 17:54:29 morpheus named[12204]: listening on IPv4 interface eth0:avahi, 169.254.10.71#53 Jun 22 17:54:29 morpheus named[12204]: listening on IPv4 interface eth1, 192.168.1.101#53 Jun 22 17:54:29 morpheus named[12204]: command channel listening on 127.0.0.1#953 Jun 22 17:54:29 morpheus named[12204]: command channel listening on ::1#953 Jun 22 17:54:29 morpheus named[12204]: zone 0.in-addr.arpa/IN: loaded serial 1 Jun 22 17:54:29 morpheus named[12204]: zone 127.in-addr.arpa/IN: loaded serial 1 Jun 22 17:54:29 morpheus named[12204]: zone 255.in-addr.arpa/IN: loaded serial 1 Jun 22 17:54:29 morpheus named[12204]: zone localhost/IN: loaded serial 1 Jun 22 17:54:29 morpheus named[12204]: running
Informing that BIND started up OK.
You can test it with dig utility (part of dnsutils package on Debian / Ubuntu systems):
# dig ornellas.apanela.com @127.0.0.1 ; <<>> DiG 9.3.4 <<>> ornellas.apanela.com @127.0.0.1 ; (1 server found) ;; global options: printcmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38994 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 3 ;; QUESTION SECTION: ;ornellas.apanela.com. IN A ;; ANSWER SECTION: ornellas.apanela.com. 11210 IN A 208.113.166.89 ;; AUTHORITY SECTION: apanela.com. 93190 IN NS ns3.dreamhost.com. apanela.com. 93190 IN NS ns1.dreamhost.com. apanela.com. 93190 IN NS ns2.dreamhost.com. ;; ADDITIONAL SECTION: ns1.dreamhost.com. 6528 IN A 66.33.206.206 ns2.dreamhost.com. 5195 IN A 208.96.10.221 ns3.dreamhost.com. 5195 IN A 66.33.216.216 ;; Query time: 1 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Fri Jun 22 17:59:10 2007 ;; MSG SIZE rcvd: 166
Note the Query time at the end. My first query gave me arroud 4000ms delay (my ISP's DNS servers are terrible). My second query (above) gave me 1ms delay. At that time, the answer was already cached, and for 11210s (see the 2nd column of the ANSWER SECITON) BIND will not query for this address. For arround 3h I will have a 1ms delay to query this address for my whole system, instead of 4s.
If you have problems at this point, please refer to BIND's documentation to enable debugging / verbosity and check the logs to find our what is wrong.
Now that we are sure BIND is working properly, we can let the whole system use it by doing this:
# echo "nameserver 127.0.0.1" > /etc/resolv.conf
This file /etc/resolv.conf stores the address of the DNS servers that the whole system uses. It should contain initially your ISP's DNS servers address. Now it contains your own DNS server address.
If you have a local network with at least a few machines, you can configure two of them to act as a local DNS cache with the above configuration. The other machines can use this two as their DNS servers at /etc/resolv.conf, letting only two machines interact with the internet. It is even possible to share queried addresses between this two internal DNS servers. Refer to BIND documentation on how to accomplish that.