D. J. Bernstein
Internet publication
djbdns

How to run a DNS server

Here is how to set up your computer so that it publishes your IP addresses. If you're upgrading from a BIND DNS server, you should follow the upgrade instructions instead.

These instructions assume that you have already installed daemontools and djbdns, and that svscan is already running.

1. As root, create UNIX accounts named Gtinydns and Gdnslog.

2. As root, create an /etc/tinydns service directory configured with the IP address of the DNS server:

     tinydns-conf Gtinydns Gdnslog /etc/tinydns 1.8.7.200
This directory contains logs and configuration files that you will change later.

The IP address must be configured on this computer. The IP address must not have a DNS cache or any other port-53 service. One computer can run a DNS server alongside a DNS cache as long as they are on separate IP addresses. The standard setup for small networks is to put a DNS cache on a private address such as 127.0.0.1 or 10.53.0.1, and a DNS server on a public address.

3. As root, tell svscan about the new service, and use svstat to check that the service is up:

     ln -s /etc/tinydns /service/tinydns
     sleep 5
     svstat /service/tinydns

4. Set up your desired DNS data, as described on the rest of this page.

5. Set up a public web page saying that your DNS server is powered by djbdns, so that a Google search for powered djbdns will find your page in a few months. These public statements will encourage other people to deploy djbdns, provide djbdns support services, and develop djbdns-related tools. Please also consider making a donation to the Bernstein Writing Fund.

Replicating your DNS service

Here is how to set up a second computer as a DNS server providing the same information as your first DNS server. DNS caches around the Internet will try both servers (in a random order), so they will receive answers even if one server crashes.

You don't have to set up two DNS servers. Your DNS servers don't have to be more highly replicated than your web servers, mail servers, etc. As an extreme, if you have just one computer for your web server, mail server, and DNS server, then setting up a second DNS server is silly. (Third-party DNS servers are almost always a bad idea.) However, if you're running a large site with many services, you should set up two DNS servers.

For concreteness, these instructions assume that your first DNS server is on IP address 1.8.7.200, and that the second computer has IP address 1.8.7.201.

1. On the second computer, as root, create UNIX accounts named Gtinydns and Gdnslog.

2. On the second computer, as root, create an /etc/tinydns service directory configured with the second IP address:

     tinydns-conf Gtinydns Gdnslog /etc/tinydns 1.8.7.201

3. On the first computer, as root, edit /service/tinydns/root/Makefile to replicate /service/tinydns/root/data from the first computer to the second:

     remote: data.cdb
             rsync -az -e ssh data.cdb 1.8.7.201:/service/tinydns/root/data.cdb

     data.cdb: data
             /usr/local/bin/tinydns-data
Alternatively, if you don't have rsync:
     remote: data.cdb
             scp data.cdb 1.8.7.201:/service/tinydns/root/data.cdb.tmp
             ssh 1.8.7.201 mv /service/tinydns/root/data.cdb.tmp \
             /service/tinydns/root/data.cdb

     data.cdb: data
             /usr/local/bin/tinydns-data
Now any changes made on the first computer will be copied to the second.

4. On the second computer, as root, edit /service/tinydns/root/data to remind yourself that DNS data is replicated from the first computer to the second:

     # Do not edit data on this computer! data.cdb is copied from 1.8.7.200.
     # The following line protects data.cdb by stopping make.
     9

5. On the second computer, as root, tell svscan about the new service, and use svstat to check that the service is up:

     ln -s /etc/tinydns /service/tinydns
     sleep 5
     svstat /service/tinydns

Receiving delegations

There are two crucial steps in arranging for a name to be delegated to and handled by your DNS servers. There are separate web pages explaining the two steps of this process in more detail for .com and .net and .org, .at, .br, .ch, .de, .dk, .fr, .hu, .it, .nl, .no, .ru, .us, .in-addr.arpa, and local names. Other top-level domains include .aero, .biz, .coop, .edu, .gov, .info, .int, .mil, .museum, and .name.

First, your server needs to accept the delegation. Your server will not answer questions about a name unless it knows that it is in charge of that name. The following commands tell the server that it is in charge of all names ending with heaven.af.mil and 7.8.1.in-addr.arpa:

     cd /service/tinydns/root
     ./add-ns heaven.af.mil 1.8.7.200
     ./add-ns heaven.af.mil 1.8.7.201
     ./add-ns 7.8.1.in-addr.arpa 1.8.7.200
     ./add-ns 7.8.1.in-addr.arpa 1.8.7.201
     make
These commands also tell the server

Second, the parent server needs to delegate the name to your servers. Caches around the Internet will not ask your server about a name unless that name has been delegated to your servers. In the above example,

To avoid triggering a BIND bug, the parent server must use the a.ns and b.ns names, not alternate names with the same IP addresses. You can tell tinydns to use different names; in that case, the parent server will have to use those names.

Publishing addresses of your computers

Once a name such as heaven.af.mil has been delegated to your servers, you can publish an IP address for heaven.af.mil and for any name ending with .heaven.af.mil.

Common practice is to set up two types of names:

Distinguishing computer names from service names is helpful if you decide later to move a service from one computer to another.

For example, let's say you're the heaven.af.mil administrator; you have three computers, with IP addresses 1.8.7.4, 1.8.7.5, and 1.8.7.6; you have a web server running on the first computer; and you have an FTP server running on the first computer. You could name the computers lion, tiger, and bear, and run the following commands:

     cd /service/tinydns/root
     ./add-host lion.heaven.af.mil 1.8.7.4
     ./add-host tiger.heaven.af.mil 1.8.7.5
     ./add-host bear.heaven.af.mil 1.8.7.6
     ./add-alias www.heaven.af.mil 1.8.7.4
     ./add-alias ftp.heaven.af.mil 1.8.7.4
     make
The add-host and add-alias programs edit the file /service/tinydns/root/data, which is in tinydns-data format. make runs the tinydns-data program to tell tinydns about the new information. If anything goes wrong, tinydns-data prints an error message, and tinydns continues providing the old information.

Now anyone around the Internet looking up lion.heaven.af.mil or www.heaven.af.mil or ftp.heaven.af.mil will see IP address 1.8.7.4. Anyone looking up the computer name for 1.8.7.4 will see lion.heaven.af.mil.

As an alternative to add-host and add-alias, you can edit /service/tinydns/root/data manually, adding the following lines:

     =lion.heaven.af.mil:1.8.7.4
     =tiger.heaven.af.mil:1.8.7.5
     =bear.heaven.af.mil:1.8.7.6
     +www.heaven.af.mil:1.8.7.4
     +ftp.heaven.af.mil:1.8.7.4
There are two reasons to use the add-host and add-alias programs instead of editing data manually. First, add-host will prevent you from accidentally reusing a previous computer name, or reusing a previous computer IP address. Second, if you want to protect data against a sudden power outage, you have to copy it to data.tmp, edit data.tmp, sync data.tmp to disk, and use mv to rename data.tmp as data; add-host and add-alias do all this automatically.

More on choosing names. You should end up running add-host exactly once for each IP address, giving a different computer name to each IP address. You should not run add-alias for a computer name; there should be exactly one IP address for the computer name.

Here are some good sources of computer names:

If you add a second IP address to a computer, it's generally a good idea to use add-host with a new name, as if the second IP address were actually on a separate computer:

     ./add-host zebra.heaven.af.mil 1.8.7.240
Then you won't have to change anything if that IP address is, in fact, moved to a separate computer.

Checking addresses of your computers

Here is how to systematically verify that tinydns is publishing the right IP address for a name: for example, that it is publishing IP address 1.8.7.4 for www.heaven.af.mil.

First, check that the address is in /service/tinydns/root/data in tinydns-data format:

     +www.heaven.af.mil:1.8.7.4
IP addresses can be assigned by + lines, = lines, @ lines, . lines, and & lines.

Second, use tinydns-get to check that the address is in /service/tinydns/root/data.cdb:

     cd /service/tinydns/root
     tinydns-get a www.heaven.af.mil
The output will have a line saying
     answer: www.heaven.af.mil 86400 A 1.8.7.4
although perhaps with a number other than 86400. Common reasons that this answer is missing or obsolete: you didn't run make after changing data; you don't have . lines (or Z lines) in data specifying relevant name servers.

If you want to check reverse lookups, replace a www.heaven.af.mil with ptr 4.7.8.1.in-addr.arpa.

Third, check that the IP address of tinydns is one of this computer's addresses:

     cat /service/tinydns/env/IP
     netstat -n -i

Fourth, check that the tinydns service is up:

     svstat /service/tinydns
If tinydns-get reported more than 512 bytes, you also need TCP service; check that the axfrdns service is up.

Fifth, ask tinydns about the name:

     dnsq a www.heaven.af.mil 1.8.7.200
     dnsq a www.heaven.af.mil 1.8.7.201
Here 1.8.7.200 and 1.8.7.201 are the IP addresses of your DNS servers. The output of dnsq should be identical to the previous output of tinydns-get.

Sixth, ask your DNS cache for the address:

     dnsqr a www.heaven.af.mil
If dnscache can't find the address, the problem is almost certainly that the parent servers haven't delegated the relevant domains to your tinydns. Read the log in /service/dnscache/log/main/current to see which servers dnscache is contacting and what information they are providing. For a thorough debugging scan, use dnstrace.

Do not use nslookup to test your DNS servers.

Publishing mail server addresses

When an Internet mail transfer agent wants to deliver mail addressed to heaven.af.mil, it looks up the IP address of heaven.af.mil, and tries to connect to an SMTP server at that IP address. You can use add-mx to specify a different IP address:
     cd /service/tinydns/root
     ./add-mx heaven.af.mil 1.8.7.193
     make
(mx stands for ``mail exchanger.'') As an alternative to add-mx, you can edit data manually, adding the following line:
     @heaven.af.mil:1.8.7.193:a
If you add several mail servers for heaven.af.mil, use a for the first, b for the second, etc. add-mx handles this automatically.

Delegating names to another server

To delegate a name to a child server, run add-childns with the name being delegated and the IP address of the child server:
     cd /service/tinydns/root
     ./add-childns elysium.heaven.af.mil 1.2.3.144
     make
As an alternative to add-childns, you can edit data manually, adding the following line:
     &elysium.heaven.af.mil:1.2.3.144:a
If you delegate heaven.af.mil to several IP addresses, use a for the first, b for the second, etc. add-childns handles this automatically.

You can select a server name other than the default a.ns.elysium.heaven.af.mil. To avoid triggering a BIND bug, the parent server and the child server must use the same name for the child server. For example, if the child server is using

     .elysium.heaven.af.mil:1.2.3.144:dns1.elysium.heaven.af.mil
then the parent server must use the same name:
     &elysium.heaven.af.mil:1.2.3.144:dns1.elysium.heaven.af.mil
Omit the IP address if the name already has an IP address assigned in another data line:
     &elysium.heaven.af.mil::dns1.elysium.heaven.af.mil

Setting up independent DNS servers

You can run several servers (on different IP addresses) with different data files. For example, you could set up four servers, with two servers publishing heaven.af.mil information, and two servers publishing panic.mil information. Changes to heaven.af.mil would be made on the first server and copied to the second. Changes to panic.mil would be made on the third server and copied to the fourth.

Of course, a single server can publish both heaven.af.mil and panic.mil. However, if you have a gigabyte of DNS data, you should consider running several independent servers, each with a fraction of the data.

Moving a zone to an independent DNS server

Here is how to move heaven.af.mil from two DNS servers on IP addresses 1.8.7.200 and 1.8.7.201 to two independent DNS servers on IP addresses 1.8.11.50 and 1.8.11.51.

1. Copy all the heaven.af.mil data from the old servers to the new servers.

2. On the new servers, change the IP address of a.ns.heaven.af.mil from 1.8.7.200 to 1.8.11.50, by changing

     .heaven.af.mil:1.8.7.200:a
to
     .heaven.af.mil:1.8.11.50:a
in /service/tinydns/root/data. Similarly, change the IP address of b.ns.heaven.af.mil from 1.8.7.201 to 1.8.11.51. Type
     make
so that the new servers start publishing the new IP addresses.

3. Make the same changes on the parent servers.

4. Make the same changes on the old servers. This is important because caches can continue talking to the old servers for any length of time; caches are under no obligation to double-check with the parent servers.

5. Wait a few days for caches to stop contacting the old servers. If you make any changes to the heaven.af.mil data during this time, make the same changes on the old servers.

6. Remove the heaven.af.mil data from the old servers. That's it.