Saturday, October 29, 2005

Installing a DNS cache with DJBDNS

This post assumes you are running some form of UNIX on your machine (Linux, Solaris, BSD, OS X, …). If you're not, you have my sympathy. Any Internet-connected computer needs a DNS server. Typically your ISP will provide this. You quite likely don't even need to know how to communicate with the DNS server; if you are using DHCP to get your host configuration it will be set up automatically. However, it can sometimes be advantageous to do a bit of the work yourself. The most effective method of improving your DNS performance is to install a cache on your local machine. A cache stores the results of DNS queries for a certain time period (IP addresses can change) and serves them back to the name-lookup software (called the resolver) in milliseconds rather than seconds. This is very handy if you visit a certain set of websites frequently. The main DNS server package on the net is BIND, the Berkeley Internet Name Domain (formerly BIN Dæmon). It powers everything from small corporate intranets to the massive high-availability root servers that underpin the entire Internet's operations. But there's a couple of problems with BIND: 1) it's historically been vulnerable to an amazing variety of security attacks and 2) it's an absolute pig to administer. O'Reilly Publishers have one of their celebrated 'animal' books devoted to DNS and BIND; it's 622 pages. Enter Daniel J. Bernstein, author of the excellent DJBDNS suite of programs. DJBDNS is markedly easier to configure than BIND, and for a long time much more secure. You can also configure it to be a lightweigfht DNS cache in minutes, just what we want. So here's how to go about it:
  1. Obtain the daemontools package. This is a set of utilities that make running a UNIX dæmon process much easier. DJBDNS requires it. It's available here. Current latest version is 0.76.
  2. Obtain the ucspi-tcp package. This is a set of programs for building client/server TCP/IP applications. It is available here. Current latest version is 0.88.
  3. Obtain the djbdns package. It is available here. Current latest version is 1.05.
  4. Build and install daemontools.
    • Unpack the daemontools tarball: tar -zxvf daemontools-0.76.tar.gz
    • cd admin/daemontools
    • If you are using Linux, cd src. Find the file conf-cc. Add the text -include /usr/include/errno.h to the first line. This is very important as otherwise gcc under Linux will fail to build the package. cd ..
    • ./package/install. This will compile and install the daemontools package, and then start the svscan process which monitors dæmon activity (if you're running BSD, just reboot). A line to start svscan on boot will be added to some initialisation file, typically /etc/inittab.
  5. Build and install ucspi-tcp.
    • Unpack the ucspi-tcp tarball: tar -zxvf ucspi-tcp-0.88.tar.gz
    • cd ucspi-tcp-0.88
    • If you are using Linux, edit the conf-cc file and add the text -include /usr/include/errno.h to the first line, just as for daemontools
    • Run make, then make setup check.
  6. Build and install djbdns
    • Unpack the djbdns tarball: tar -zxvf djbdns-10.5.tar.gz.
    • cd djbdns-1.05. If you are using Linux, edit the conf-cc file and add the text -include /usr/include/errno.h to the first line, just as for daemontools
    • Run make, then make setup check.
  7. Check your DNS is OK: dnsq a <IP of a DNS server>. You need to supply the IP address of an external DNS server. If you know the IP addresses of your ISP's nameservers, then use one of them. If not, then now is a good time to get onto Tech Support and get that info. You're going to need it later. If all is well, then you should see a bunch of lines like the following: authority: com 172800 NS and additional: 172800 A If this request times out, then you have a problem getting on the Internet. It could be that a firewall is blocking requests on port 53 (DNS), but that's unlikely since I assume you've had connectivity before installing DJBDNS. If it is a firewall problem then you will need to allow outgoing connections to port 53 from ports 1024–65535 on your local machine.
  8. Create dummy users for the DNS cache and log functions: useradd gdnscache -s /bin/false and useradd gdnslog -s /bin/false.
  9. Set up the dnscache service: dnscache-conf gdnscache gdnslog /etc/dnscache. This will create directories called root and log under the /etc/dnscache directory. DJBDNS runs in a chroot jail in /etc/dnscache/root.
  10. Link the DNS cache directory to /service: ln -s /etc/dnscahce /service. Wait five seconds. svscan will pick up the new service and start it. To check it is running, type svstat /service/dnscache. You should see a line indicating the service is running, along with its PID.
  11. Edit your /etc/resolv.conf file. Include the single line nameserver, and remove or comment out any others.
  12. Check you can resolve hosts: dnsip You should get Google's IP addresses. Then try accessing a website.
  13. Open the file /etc/dnscache/root/servers/@. You will see a bunch of IP addresses. These are root servers. At the top of this file, one per line, add the addresses of your ISP's name servers.
  14. Restart djbdns: type svc -t /service/dnscache
And that's it. You should notice an improvement in DNS response times. ADDENDUM: you can alter the size of the dnscache in-memory file. The default size is one Megabyte, but if you've got plenty of RAM there's no harm in increasing it. I have 1G of RAM so I set the cache to be 10Mb. The files to control this are in /etc/dnscache/env. To set the cache to be 10Mb, type the following: echo 10000000 > CACHESIZE and echo 10485760 > DATALIMIT. Then restart DNS: svc -t /service/dnscache. If you now look at the dnscache process (I use ps acvxwww | grep dnsca) you will see that its Resident Set Size is a little over 10Mb.