Hacking Linux Exposed





previous article
next article
DJBDNS: The Pieces
By Bri Hatch.

Summary: DJBDNS is only as effective as the sum of its parts. Understanding the different pieces that constitute DJBDNS is the first step to effectively deploying it.

DJBDNS has many separate pieces, not all of which you necessarily need. The separate pieces include:

This is the recursive caching name server, which simply looks up the DNS records you request. It consults the thirteen root DNS servers and winds it's way up to the answer. You can also associate zones with name servers manually to support non-official zones, such as internal networks. dnscache listens on both TCP and UDP port 53.

This is the DNS server you run to let others resolve your hostnames and IP addresses. It will only serve the data that you've given it, so you cannot point to it as your default name server -- point to a dnscache IP address instead. tinydns listens on UDP port 53.

This server allows authorized BIND secondary DNS servers to mirror your zone files. The 'official' DJBDNS way to synchronize zones is to simply rsync the files from the master to the slaves. However, for compatibility with BIND's zone transfers, you can run axfrdns. axfrdns listens to TCP port 53.

You may have noticed above that dnscache and tinydns both want to listen on UDP port 53. That means that you cannot have both of these processes listening on the same IP address. DJB's official retort is that you should be using separate machines for this purpose anyway, which is pretty much true. However, if you want to run both on the same machine, then you can run each on it's own virtual IP address (eth0:0 vs eth0:1, etc...) or you could run dnscache on localhost (available only to that machine) and tinydns on the external interface. The network setup you pick will depend on your needs.

Each of these servers are run through the supervise/svscan processes we installed earlier. These processes require a special directory layout to define the programs to run; however, you can run configuration programs to handle the grunt work. Let's start off by setting up dnscache:

# dnscache-conf dnscache dnslog /etc/dnscache

The arguments are:

  • dnscache -- The user the daemon will run as.
  • dnslog -- the user the logging component will run as.
  • /etc/dnscache -- The directory to set up for supervise.
  • -- The IP address dnscache should listen on.

For now I'm setting the IP address to be because it's a convenient way to test things.[1] If you already have BIND listening on localhost ( then using won't conflict and we can verify all is well before turning off BIND.

This creates the following directories inside /etc/dnscache:

Any files in here are environment variables that will be set for the dnscache process. For example the file 'IP' contains '' for our current setup. Dnscache uses environment variables for all its configuration. Unless you have a good reason, leave the other files as they are. IP is fair game to change later on.
The logging for dnscache is handled by multilog (part of daemontools), which will run in this directory.
The actual logs go here, automatically rotated for you. The file 'log/main/current' is always the most current log.
The command that supervise runs to start dnscache.
A directory used by supervise to keep dnscache running or restart when needed.
The directory into which dnscache will chroot upon startup.

All DJBDNS software uses this same directory layout. However the stuff that is in root differs from application to application. In the case of dnscache, the root directory contains files that function as follows:

Dnscache will not answer queries from unauthorized hosts. If a machine with an IP address W.X.Y.Z contacts this server, dnscache will answer if it finds a file in the root/ip/ directory named "W.X.Y.Z", "W.X.Y", "W.X", or "W". The presence of an appropriate file is all that's required -- the contents of the file are unimportant. (Typically you just create empty files, for example 'touch 192.168' to grant access to all machines in 192.168.x.y.)
This directory contains lists of servers to contact for specific zones. By default a file named '@' is installed which contains the IP addresses of the 13 root DNS servers. If you wish to point to zones that would not be found by starting at the root DNS servers, such as an internal network, then you'd create files here to point to them.[2]

dnscache-conf will automatically install a root/ip/ file, but you'll need to add any additional files to allow other IPs or networks to be allowed. For now, since we are running dnscache on port, no other machines could connect anyway.[3] If you have any internal domains that'd you'd need to point to manually, create the appropriate files in root/servers/.

Now we need to tell svscan to start dnscache:

# ln -s /etc/dnscache /service

In five seconds, svscan should start up dnscache. (Remember, it's watching that /service directory.) It's now time to see if things are working correctly. First, do a quick lookup of your favorite hostname against your current DNS server[4]:

$ host example.com
example.com has address

Then verify that dnscache is providing the same data:

$ host example.com
example.com has address

This time I hard-coded the address to query against our local dnscache process. Make sure to check any internal domains, including reverse lookups. If you're only using BIND for a DNS cache, not serving local DNS data, then you can turn BIND off and put dnscache into production. Just make sure to change the env/IP file to have the correct IP address on which dnscache should listen, and be sure to add the appropriate files in root/ip to make sure local clients can connect.

If you are serving DNS data with BIND, then you may be able to separate things by having dnscache listen on an IP address not in use by BIND (set BIND's listen-on directive in /etc/named.conf) until you can configure tinydns to serve up the data, at which point you can be BIND free.

Worst case scenario, you should be able to have BIND listen only on your external IP address:

	listen-on { IP.AD.DR.ES; };

and have dnscache on localhost

# echo > /etc/dnscache/env/IP

and point this machine to dnscache instead of BIND:

$ cat /etc/resolv.conf
search domain.dom

So, let's restart BIND:

# killall -HUP named

and then stop/restart the dnscache program on the new IP address.

# svc -d /etc/dnscache
# svc -u /etc/dnscache

That's it. Next week: tinydns.


[1] Although folks usually think of localhost as, all of the 127.x.y.z network is locally usable as well, without any additional configuration or ifconfig commands. Cool, eh?

[2] Examples: If you had an internal zone 'inside.example.com' that is served by and, then create a file named 'inside.example.com' with those two IP addresses each on their own line. If you want to point to those machines for the reverse DNS entries for the 192.168.1.x network, put those IP addresses in a file named 1.168.192.in-addr.arpa. If you've administered DNS before, this backwards notation should look familiar.

[3] Assuming you have appropriate kernel ACLs in place (ipchains/iptables) to disallow connections to localhost from external interfaces. This is a *really* good idea....

[4] example.com's IP address may change by the time you read this, or they delete the A record entirely. I don't know why they ever gave it one in the first place....

Bri Hatch is Chief Hacker at Onsight, Inc, and author of Hacking Linux Exposed and Building Linux VPNs. He has a hard time believing all these folks who say you don't need air conditioning in Seattle, when his apartment was still 91 degrees at 2am. Bri can be reached at bri@hackinglinuxexposed.com.

Copyright Bri Hatch, 2002.

This article was first published here in ITworld.com Inc., 118 Turnpike Rd., Southborough, MA 01772  on 30-Jul-2002.

previous article
next article