Setting up TinyDNS on Amazon’s Linux

If you need to setup both a DNS Server and DNS Cache, consider http://www.fefe.de/djbdns/#splithorizon – there are some issues with the points below that need to be resolved (specifically the resolv.conf pointing to the dnscache, without pointing the dnscache at the djbdns).

DNS nameservers serve the purpose of mapping a domain name to an IP address. Typically, an individual machine does not have the DNS information needed to resolve a wide range of domain names, and must rely on lookups to other servers to accomplish this task. As each request takes time, and forces a dependence on other servers, it is often preferable to host your own nameserver for frequently accessed domains.

A typical example of such domains might include those that are hosted by the server. In this case, we are not trying to replace the primary nameserver that ‘the public’ will be using for resolution of our domain names, but rather, trying to avoid making our server lookup DNS information for sites located on the server.

The commonly used caching  nameserver is BIND (aka named), it is well documented, and available in the repositories of most distributions (including the amzn repository). However, it has a significant memory footprint, and is unnecessary for the purposes outlined above. A good replacement is TinyDNS (aka djbdns). This is package serves as a caching nameserver and dns server, is light-weight, fairly easy to configure, and comprised of several individual components.

The following steps will outline a procedure for installing TinyDNS on Amazon’s Linux distribution (RHEL-like), and show a basic, manual configuration of the data file for single server hosting multiple sites (with public nameservers hosted elsewhere).

The first thing to setup is daemontools, the software that manages the running of the DNS services:

cd /usr/local/bin
wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz
tar -xzvf daemontools-0.76.tar.gz
mv admin daemontools
cd daemontools/daemontools-0.76
sed -i 's/^gcc.*/& -include \/usr\/include\/errno.h/' src/conf-cc
./package/install

The download location is a personal preference, most of the above should be self explanatory, except for the second last line. The second last line appends a path to a header file at the end of the gcc line of conf-cc; this is needed to address a compilation problem that would otherwise occur.

Cleanup:

rm –f /usr/local/src/daemontools-0.76.tar.gz

You cannot delete the command folder that is created by the install script, as the scripts it installs are symlinked to files in that folder.

The next step, very similar to the one above, is to compile and install djbdns:

cd /usr/local/src
wget http://cr.yp.to/djbdns/djbdns-1.05.tar.gz
tar -xzvf djbdns-1.05.tar.gz
cd djbdns-1.05
sed -i 's/^gcc.*/& -include \/usr\/include\/errno.h/' conf-cc
make && make setup check

Cleanup:

rm –f /usr/local/src/djbdns-1.05.tar.gz
rm –rf /usr/local/src/djbdns-1.05

It is now necessary to setup two system users, and set the IP that tinydns will listen on (usually the external IP).

useradd -d /var/dnscache -s /bin/false tinydns
useradd -d /var/dnscache -s /bin/false tinylog
/usr/local/bin/tinydns-conf tinydns tinylog /var/dnscache/tinydns YOUR_EXTERNAL_IP

Finally, we are going to setup some entries for TinyDNS. There are scripts located in /var/dnscache/tinydns/root that can be used, or, for more versatility, the entries can be created manually.

The scripts are:

Script and Parameters Records Added
add-alias  <domain> <ip> A
add-childns  <domain> <ip> NS, A
add-host  <domain> <ip> A, PTR
add-mx  <domain> <ip> MX, A
add-ns<domain> <ip> SOA, NS, A

Each of these modifies the contents of the file /var/dnscache/tinydns/root/data

The ‘data’ file must be compiled into tinydns’ database format using ‘make

Finally, we symlink tinydns to the service directory that is being monitored by daemontools.

ln -sf /var/dnscache/tinydns /service

Considerably more flexibility can be leveraged by directly editing the ‘data’ file. It is in a simple format, which each, plain text line corresponding to a specific set of records, denoted by the first character of the line. The rest of the line contains values separated by colons (:).

Start Records Fields
. NS, A, SOA <domain>:<ip>:<ns_prefix>:<time_to_live>
& NS, A <domain>:<ip>:<ns_prefix>:<time_to_live>
= A, PTR <domain>:<ip>:<time_to_live>
+ A <domain>:<ip>:<time_to_live>
@ MX, A <domain>:<ip>:<prefix>:<priority>:<time_to_live>
TXT <domain>:<string>:<time_to_live>
^ PTR <domain>:<points_to>:<time_to_live>
C CNAME <domain>:<points_to>:<prefix>:<time_to_live>

Each record may also contain option timestamp and location fields (last two fields) for a line. Further specifics can be found at: http://cr.yp.to/djbdns/tinydns-data.html. Much like with BIND, the use of CNAMEs appears to be frowned upon, and it is preferable to use A records instead.

A reasonable setup might resemble the following (can be repeated for each domain hosted):

.example.com:11.22.33.44::259200
@example.com:11.22.33.44:mail.example.com::86400
+www.example.com:11.22.33.44:86400
+ftp.example.com:11.22.33.44:86400

Do not forget to run ‘make’ after saving the ‘data’ file.

You can verify that TinyDNS is running by executing:

ps -ef | grep dns

Which should return at least two processes:

supervise tinydns
/usr/local/bin/tinydns

To make the server start using the new DNS server, modify /etc/resolv.conf, and prepend nameserver 127.0.0.1. Amazon’s Linux automatically creates this file – for practicality, keep the existing nameserver entry, and put your new nameserver entry above it. Since this file is automatically recreated at startup, you must modify the creation script (/sbin/dhclient-script) for the setting to persist between reboots.

Insert echo nameserver 127.0.0.1 >> $rscf at line 68, as below:

/sbin/dhclient-script:

.
.
.
65:    if [ -n "$RES_OPTIONS" ]; then
66:      echo options $RES_OPTIONS >> $rscf
67:    fi
68:    echo nameserver 127.0.0.1 >> $rscf
69:    for nameserver in $new_domain_name_servers; do
70:      echo nameserver $nameserver >> $rscf
71:    done
.
.
.

To verify that the server is using TinyDNS, try:

dig example.com

In addition to the information being correct, you should notice a line near the bottom that reads:

;; SERVER: 127.0.0.1#53(127.0.0.1)

If you wish to setup the DNS cache, create two users, set the cache to listen on the loopback address (normally you would need to specify addresses allowed to access the cache, but that does not appear to be needed on the local machine), and symlink dnscacheto the service directory being monitored by daemontools.

useradd -d /var/dnscache -s /bin/false dnscache
useradd -d /var/dnscache -s /bin/false dnslog
/usr/local/bin/dnscache-conf dnscache dnslog /var/dnscache/dnscache 127.0.0.1
ln -sf /var/dnscache/dnscache /service/

If you wish to setup ucspi-tcp, the procedure is very similar to those above:

cd /usr/local/src
wget http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz
tar -xzvf ucspi-tcp-0.88.tar.gz
cd ucspi-tcp-0.88
sed -i 's/^gcc.*/& -include \/usr\/include\/errno.h/' conf-cc
make && make setup check

Cleanup:

rm –f /usr/local/src/ucspi-tcp-0.88.tar.gz
rm –rf /usr/local/src/ucspi-tcp-0.88

Overall, compared to BIND, this seems like an excellent solution. In the first place, the memory usage is negligible, with response time being nearly instant. Furthermore, it eliminates a slight annoyance – the file system loop caused by running BIND chrooted.

A few quick addendums
Since this setup uses DaemonTools, starting, stopping, and monitoring tinydns and dnscache is done through svc and svstat:

Status:

/usr/local/bin/svstat /service/tinydns

Start:

/usr/local/bin/svc -u /service/tinydns

Stop:

/usr/local/bin/svc -d /service/tinydns

Reload (HUP):

/usr/local/bin/svc -h /service/tinydns

Pause:

/usr/local/bin/svc -p /service/tinydns

Continue:

/usr/local/bin/svc -c /service/tinydns

All of the above will also work with dnscache.

Some authentication mechanisms (including SSH) typically perform reverse DNS checks, and, will be affected by an incorrectly configured (or corrupt) DNS cache (typically manifesting as very slow logins (SSH, FTP) on an otherwise fast system).

By cyberx86

Just a random guy who dabbles with assorted technologies yet works in a completely unrelated field.

1 comment

Leave a comment

Your email address will not be published. Required fields are marked *