In this Daily Drill Down, Vincent Danen shows you how to get rid of the buggy Berkeley Internet Name Daemon (BIND) in order to avoid the pitfalls of malicious Linux viruses, such as the Lion worm.
March 23, 2001: The Lion worm runs rampant around the world, infecting Linux DNS servers that are using ISC's BIND software. Lion targets port 53, the standard port to which DNS servers listen, takes advantage of some known exploits in the BIND software, installs the t0rn rootkit (which replaces essential system binaries), and propagates itself.
The Lion worm, similar to the Ramen worm in concept, is purely malicious. This worm is out to destroy your system. Fortunately, the vulnerabilities it takes advantage of are publicly known, and the conscientious system administrator who knows to pay attention to vendor updates and upgrade them should not be affected. Lion cannot affect BIND version 8.2.3, the last full release of the 8.x series. Most vendors made releases available at the end of January to correct these problems.
The unfortunate thing is that this is just the latest in a rash of insecurities found in the BIND code. Many people have criticized BIND as being insecure software that's full of bugs, and the number of updates to the code prompted by discovered security vulnerabilities makes this abundantly clear. However, even though people criticize BIND, they continue to use it. Why? It's the most popular DNS server on the Internet for UNIX systems. It's been around as long as the Internet has and is a de facto standard for DNS operations.
It's also a de facto security problem. The ISC claims that the next generation of BIND, the 9.x series, has been completely rewritten and is more secure than the 8.x series. This remains to be seen. The 9.x series of BIND has had security problems itself, although according to SANS, it cannot be used to propagate the Lion worm. So it's safe...for now.
There are alternate DNS servers available, and I believe many system administrators are not aware of this. It might be because they mistakenly believe that BIND is the only package to do the job, or they simply have not taken the initiative or had the time to look for alternatives. Quite a few exist, with varying degrees of complexity and usefulness.
One DNS server that has been around awhile is the djbdns server. The djbdns server package was written with security and stability in mind and is recommended as a secure alternative to BIND. It was also written by the author of Qmail, which is a secure e-mail mail transport agent (MTA) that is easier to configure and more secure than other popular mail servers like Sendmail.
Like Qmail, djbdns uses a modular design that utilizes different users for different tasks. Naturally, djbdns is never run as root, which prevents root compromises. Each aspect of djbdns is run as a different user, so if any part of the server does happen to be compromised, damage is extremely limited. Thus, compromising one part of the DNS server does not necessarily mean the entire server is compromised. Unlike BIND, the programs are also split into several smaller programs, which further reduces potential damage should the system be compromised. For those just needing a caching name server, you can run a slim djbdns server to provide caching-only services. With BIND, you must run everything or nothing, which increases potential security holes.
In this two-part Daily Drill Down, I will explain how to install and configure the djbdns server and remove BIND from the system, which will provide you with a secure DNS solution that is invulnerable to current worms like Lion and future worms that may take advantage of any unfound security problems that may arise.
The first thing to do is to download djbdns from the djbdns Web site. The current version of djbdns is 1.05, so download the TAR/GZip archive and save it to your /usr/local/src directory. If you do not have the daemontools and ucspi-tcp packages installed (if you don't use Qmail, chances are you don't), then download those programs, as well. (Daemontools is currently at version 0.70, and ucspi-tcp is at version 0.88.)
If you look in your /usr/local/src directory, you should have three source packages:
You will first need to build and install daemontools and ucspi-tcp prior to installing djbdns. Let's first build the daemontools package. Untar the package and build, and then install the program using the following:
tar xvzf daemontools-0.70.tar.gz
make setup check
After you have installed daemontools, go back to /usr/local/src and do the same for ucspi-tcp using the following:
tar xvzf ucspi-tcp-0.88.tar.gz
make setup check
Once that is complete, use this to install djbdns:
tar xvzf djbdns-1.05.tar.gz
make setup check
That's all there is to it! The daemontools and ucspi-tcp do not need any extra configuration. Once they are installed, they are ready to go to work for you. Now that you have djbdns built and ready to run, let's take a look at configuring it.
Using djbdns as a caching name server
You will need to create a /service directory for svscan, the monitoring program that will load djbdns when required. The svscan monitoring program is part of the daemontools package and is used to talk to servers and control certain aspects of their behavior. To do this, simply execute the following:
chmod 755 /service
Now, you will need to determine how you are going to start svscan. The simplest way to do so is to add a line to your /etc/inittab file. Click here to view the line to add.
Make sure you put it all on one line at the end of the /etc/inittab file. To start svscan immediately, just execute the same command on the command line, like so:
svscan /service </dev/null >/dev/console 2>/dev/console
Now, you can set up djbdns to act as a caching name server. Before you proceed with configuring djbdns, however, you will need to create two user accounts: dnscache and dnslog. You will also need to make a group to which the accounts will belong, and I personally prefer to use the group djbdns for the user accounts. So make the group djbdns and the user accounts by executing these commands.
The first command creates the system group djbdns and assigns it a group identification number (gid) of 405, which is usually unused on any system. The second and third commands create the dnscache and dnslog users, respectively, assigning them both the shell /bin/true, which is a nonexistent shell to prevent actual logins, and the user identification numbers (uids) of 410 and 411, respectively, both of which are usually unused uids.
To ensure that those uid and gid values are not being used on the system, you should check your /etc/group and /etc/passwd files using grep like this:
grep 405 /etc/group
grep 410 /etc/passwd
grep 411 /etc/passwd
If nothing is returned, then you know those uid and gid values are unused on your system, and they are safe to use. I arbitrarily selected those uid and gid values because they are typically unused on any Linux distribution.
Now that your users and groups are set up, you are ready to configure your caching DNS server. Next, run the dnscache-conf program, which is by default located in /usr/local/bin, to set up the caching name server. Execute dnscache-conf like this:
dnscache-conf dnscache dnslog /etc/dnscachex 192.168.5.38
This creates the dnscache environment in the /etc/dnscachex directory which, as you recall, is the home directory you previously assigned to your dnslog and dnscache users. The IP address specified in the configuration is the IP address of the machine on which you are installing, so this assumes your IP address is 192.168.5.38.
Next, you must tell the cache to accept queries from certain IP addresses. This is done by placing 0 byte files that are named after allowed IP addresses in the /etc/dnscachex/root/ip directory. For instance, to allow all 192.168.5.* computers to use this machine for DNS queries (lookups), you would use:
You can be more selective and allow, for example, only 192.168.5.55 to be able to use the system for DNS queries by using:
Finally, you must create a symbolic link to /etc/dnscachex to the /service directory so that svscan knows about the service. Then, svscan will automatically start the service roughly five seconds after creating the symbolic link. Create the link using:
ln -s /etc/dnscachex /service/
After you wait a few seconds, run:
and it will tell you whether or not the service is up and running. It will report something similar to this if it is up and running:
/service/dnscachex/: up (pid 1150) 23 seconds
Next, edit your /etc/resolv.conf file to tell the system to use your own system for DNS queries by inserting into the file:
name server 192.168.5.38
and removing any other name server definitions stored in the file. That's all you need to do! You now have a working caching name server, free of the problems and security flaws that are typically associated with the BIND server. Now you don't have to worry about the Lion worm.
Using djbdns as a full name server
Using a caching name server is useful for LANs or home systems, but if you currently use BIND to make your domain known to the Internet, the caching DNS server is not what you want or need. You need a full-fledged DNS server. To do this, you need to configure djbdns in a slightly different way.
You still need to create users on the system, but this time you will need to create three users: dnslog, axfrdns, and tinydns. You do this by executing these commands.
This creates the same djbdns group and the same dnslog user. However, instead of creating the dnscache user, you're creating tinydns and axfrdns users. Next, run the tinydns-conf program to configure tinydns, which is the server that responds to DNS queries from other servers by using this command:
tinydns-conf tinydns dnslog /etc/tinydns 184.108.40.206
This installs configuration files and programs in the /etc/tinydns directory and tells tinydns that your IP address is 220.127.116.11. Next, run the axfrdns-conf program to configure axfrdns, which is the server that handles zone transfers to and from other servers with this command.
This installs configuration files and programs in the /etc/axfrdns directory and tells axfrdns your IP address. It also lets axfrdns know where tinydns is located. The next step is to tell axfrdns from which systems to allow zone transfers. This is where you will configure your secondary name servers and any third-party servers you may use. You can tell axfrdns to allow zone transfers from 18.104.22.168, your secondary DNS server, by placing this:
into the file /etc/axfrdns.tcp. Include similar lines for any secondary or third-party DNS servers from which you wish to allow zone transfers. Finally, you will need to add the following line to the same file to allow nonzone transfer TCP connections from anywhere on the Internet:
Your /etc/axfrdns.tcp file in its entirety would look like:
Now, you need to create a hashed database for axfrdns to read. You can do this by executing the make command in the /etc/axfrdns directory like this:
You will also need to do this on any secondary djbdns servers you will be setting up. (Install the same programs and configure axfrdns and tinydns the exact same way, but change the IP address used to the IP address of your secondary server.)
Next, you need to arrange for replication of data between your primary and secondary DNS servers. Where BIND did this internally, djbdns takes a different, more secure approach. The djbdns server program makes use of the rsync program and tunnels everything through ssh to take advantage of secure encrypted communication. This is done by transferring the /etc/tinydns/root/data file from the primary server to the secondary. On the primary server, in this case 22.214.171.124, you would edit the /etc/tinydns/root/Makefile file to look like this example.
On the secondary server, 126.96.36.199, you would also edit the /etc/tinydns/root/Makefile but in that file, you would place this code.
As you can see, where BIND uses multiple files for various zones, djbdns uses a single file, /etc/tinydns/root/data, which gets compiled into a special hashed database called /etc/tinydns/root/data.cdb. This file is copied to the secondary server using rsync so it provides the exact same information as the primary server.
At this point, the server itself is configured. To make svscan aware of both tinydns and axfrdns, create symbolic links like you would when installing the caching name server, using the following:
ln -s /etc/tinydns /service/
ln -s /etc/axfrdns /service/
However, I do not recommend creating those symbolic links until you have removed BIND from your system. Because the default port for DNS servers is port 53, svscan will be unable to start the tinydns server until you have removed, or at least stopped, the BIND server which will already be bound to that port.
Of course, at this point, your servers have nothing to serve. You still need to populate your DNS server with information to provide to the world about your domain(s). We will take a look at populating the /etc/tinydns/root/data file in the next part of this two-part series.
As you can see by the installation and configuration of djbdns, it is a very different system from BIND. Its configuration is not necessarily more difficult than BIND's, just different. If you're accustomed to using BIND, using djbdns will be a bit of a learning curve for you.
Since djbdns was designed with security in mind and uses a secure model throughout, it can be a little trying the first time around, but I hope that my explanations and examples have provided you with enough information to get started easily and quickly. In the second and final part of this series, I will look at obtaining zone information from your existing BIND servers and importing this information into djbdns.
Vincent Danen works on the Red Hat Security Response Team and lives in Canada. He has been writing about and developing on Linux for over 10 years and is a veteran Mac user.