The Linux Guide Online

Chapter 05 - DNS

5.1 Introduction

TCP/IP networking revolves around 32-bit numbers which are used to uniquely identify a resource on the Internet. However, you will have a hard time remembering more than a few of these. Therefore, hosts are generally known by ``ordinary'' names, that can be easily remembered like www.yahoo.com. It is then the application's duty to find the IP-address corresponding to this name. This process is called host name resolution.

Now, on a small network like an Ethernet, or even a cluster of them, it is not very difficult to maintain tables mapping host names to addresses. This information is usually kept in a file named /etc/hosts. When adding or removing hosts, or reassigning addresses, all you have to do is update the hosts on all hosts. Quite obviously, this will become burdensome with networks than comprise more than a handful of machines.

On the Internet, address information was initially stored in a single HOSTS.TXT database, too. This file was maintained at the Network Information Center, or NIC, and had to be downloaded and installed by all participating sites. When the network grew, several problems with this scheme arose. Beside the administrative overhead involved in installing HOSTS.TXT regularly, the load on the servers that distributed it became too high. Even more severe was the problem that all names had to be registered with the NIC, which had to make sure that no name was issued twice.

This is why, in 1984, a new name resolution scheme has been adopted, the Domain Name System. DNS was designed by Paul Mockapetris, and addresses both problems simultaneously.

5.2 The Domain Name System

DNS organizes host names in a hierarchy of domains. A domain is a collection of sites that are related in some sense--- be it because they form a proper network (e.g. all machines on a campus, or all hosts on BITNET), because they all belong to a certain organization (like the U.S. government), or because they're simply geographically close. The complete name of a host in this way using all the hierarchy of domains is called the fully qualified domain name. This name uniquely identifies a machine to the Internet.

Now, organizing the name space in a hierarchy of domain names nicely solves the problem of name uniqueness; with DNS, a host name has to be unique only within its domain to give it a name different from all other hosts world-wide. Thus the name of a host name yahoo could be used in multiple instances - yahoo.com (the com domain) and the yahoo.co.in (the company network for India). Furthermore, fully qualified names are quite easy to remember. Taken by themselves, these are already very good reasons to split up a large domain into several sub-domains.

But DNS does even more for you than this: it allows you to delegate authority over a sub-domain to its administrators. For example, the maintainers at any top-level domain may use the assigned IP addresses in any fashion they like and name the machines according to their own convention. It however suffices only for the DNS of that administrator is updated. All the changes then automatically propagate through the rest of the world about any new host name that is setup. To this end, the name space is split up into zones, each rooted at a domain. Note the subtle difference between a zone and a domain: the domain university.edu encompasses all hosts at the University, while the zone university.edu includes only the hosts that are managed by the Computing Center directly, for example those at the Mathematics Department. The hosts at the Physics Department belong to a different zone, namely physics.university.edu although there are in the same zone. Hence the domain name serving for a particular domain only is the responsibility of that department's DNS.

In short, DNS is the Domain Name System that converts machine names to the IP addresses that all machines on the net have. It translates (or "maps" as the jargon would have it) from name to address and from address to name, and some other things. The mapping can be from the domain name to the IP address or vice versa. These processes are called the "lookup" and the "reverse lookup".

Before you start on this you should configure your machine so that you can telnet in and out of it, and successfully make all kinds of connections to the net, and you should especially be able to do telnet 127.0.0.1 and get your own machine (test it now!). You also need good /etc/nsswitch.conf, /etc/resolv.conf and /etc/hosts files as a starting point, since we will not explain their function here. If you don't already have all this set up read the chapters on networking. It is also assumed that you are not behind any firewall because that complicates the setup. The case of setting up a DNS behind a firewall is not discussed here.

5.3 Installation

Name serving on Unix or Linux is done by a program called named (or the name daemon). This is a part of the ``BIND'' package which is coordinated by The Internet Software Consortium. Named is included in most Linux distributions and is usually installed as /usr/sbin/named, usually from a package called BIND.

You probably need to get the rpm for the bind package, either locally or from the Red Hat ftp site. Then install the package using the standard rpm command.

rpm -ivh bind<version>.rpm
rpm -ivh bindconf<version>.rpm
rpm -ivh cashing-nameserver<version>.rpm
rpm -ivh bind-utils<version>.rpm

Where version is either the name of the latest updated version for a particular distribution.

A word of caution here. Bind program is one program, due to the sensitivity of its function, that is very prone to attacks across a network. All good system administrators must keep in touch with the latest developments and keep their version of bind up to date. Over the last few years considerable work has been done on this program and it is being made more difficult to crack. If you are security conscious, update your rpm to the latest.

5.4 The Cashing-only nameserver

This is a special type of nameserver that you can setup. A caching only name server will find the answer to name queries and remember the answer the next time you need it. This will shorten the waiting time the next time significantly, especially if you're on a slow connection.

The process involved in setting up a cashing only nameserver is easy. It is suggested that you look up one of the many sites that deal with information about the setup and copy the necessary configuration files. This setup will not be discussed here.

5.5 A simple domain.

Some basic theory is in order here.

DNS is a hierarchical, tree structured, system. The top is written '.' and pronounced 'root', as is usual for tree data-structures. Under . there are a number of Top Level Domains (TLDs); the best known ones are ORG, COM, EDU and NET, but there are many more. Just like a tree it has a root and it branches out.

When looking for a machine the query proceeds recursively into the hierarchy starting at the root. If you want to find the address of prep.ai.mit.edu., your nameserver has to start asking somewhere. It starts by looking it its cache. If it knows the answer, having cached it before, it will answer right away. If it does not know it will remove parts from the name starting at the left, checking if it knows anything about ai.mit.edu., then mit.edu., then edu. and if not that it does know about . because that was in the hints file. It will then ask a '.' server about prep.ai.mit.edu. This '.' server will not know the answer, but it will help your server on its way by giving a referral, telling it where to look instead. These referrals will eventually lead your server to a nameserver that knows the answer.

Traditionally the program used to do domain name lookups is the nslookup program. It is used as

$ nslookup prep.ai.mit.edu

Nowadays it is suggested that the dig program be used, and the nslookup program is being made obsolete. The following discussion used the dig program to illustrate.

The process of lookup looks to ultimately find a "ANSWER SECTION", and an answer for our lookup. The "AUTHORITY SECTION" contains information about which servers to ask about ai.mit.edu the next time. So you can ask them directly the next time you wonder about ai.mit.edu names.

In the tree analogue each '.' in the name is a branching point. And each part between the '.'s are the names of individual branches in the tree. One climbs the tree by taking the name we want (prep.ai.mit.edu) asking the root (.) or whatever servers father from the root toward prep.ai.mit.edu we have information about in the cache. Once the cache limits are reached the recursive resolver goes out asking servers, pursuing referrals further into the name.

A much less talked about, but just as important domain is in-addr.arpa. It too is nested like the `normal' domains. in-addr.arpa allows us to get the host's name when we have its address that is for the 'reverse lookup'. A important thing to note here is that the IP addresses are written in reverse order in the in-addr.arpa domain. If you have the address of a machine: 192.148.52.43 named proceeds just like for the prep.ai.mit.edu example: find arpa. servers. Find in-addr.arpa. servers, find 192.in-addr.arpa. servers, find 148.192.in-addr.arpa. servers, find 52.148.192.in-addr.arpa. servers. Find needed records for 43.52.148.192.in-addr.arpa.

5.6 Our own domain

Now to define our own domain. We're going to make the domain linux.bogus and define machines in it. I use a totally bogus domain name to make sure we do not clash with anyone else on the Internet.

One more thing before we start: Not all characters are allowed in host names. We're restricted to the characters of the English alphabet: a-z, and numbers 0-9 and the character '-' (dash). Keep to those characters. Upper and lower-case characters are the same for DNS, so pat.uio.no is identical to Pat.UiO.No.

We've already started this part with this line in named.conf:

zone "0.0.127.in-addr.arpa" {
type master;
file "pz/127.0.0";
};


Please note the lack of `.' at the end of the domain names in this file. This says that now we will define the zone 0.0.127.in-addr.arpa, that we're the master server for it and that it is stored in a file called pz/127.0.0. This file reads:

$TTL 3D
@ IN SOA ns.linux.bogus. hostmaster.linux.bogus. (
1 ; Serial
8H ; Refresh
2H ; Retry
4W ; Expire
1D) ; Minimum TTL
NS ns.linux.bogus.
1 PTR localhost.

Please note the `.' at the end of all the full domain names in this file, in contrast to the named.conf file above. Some people like to start each zone file with a $ORIGIN directive, but this is superfluous. The origin (where in the DNS hierarchy it belongs) of a zone file is specified in the zone section of the named.conf file; in this case it's 0.0.127.in-addr.arpa.


This `zone file' contains 3 `resource records' (RRs): A SOA RR. A NS RR and a PTR RR. SOA is short for Start Of Authority. The `@' is a special notation meaning the origin, and since the `domain' column for this file says 0.0.127.in-addr.arpa the first line really means


0.0.127.in-addr.arpa. IN SOA ...


NS is the Name Server RR. There is no '@' at the start of this line; it is implicit since the previous line started with a '@'. Saves some typing that. So the NS line could also be written


0.0.127.in-addr.arpa. IN NS ns.linux.bogus


It tells DNS what machine is the name server of the domain 0.0.127.in-addr.arpa, it is ns.linux.bogus. 'ns' is a customary name for name-servers, but as with web servers who are customarily named www.something the name may be anything.


And finally the PTR (Domain Name Pointer) record says that the host at address 1 in the subnet 0.0.127.in-addr.arpa, i.e., 127.0.0.1 is named localhost.


The SOA record is the preamble to all zone files, and there should be exactly one in each zone file. It describes the zone, where it comes from (a machine called ns.linux.bogus), who is responsible for its contents (hostmaster@linux.bogus; you should insert your e-mail address here), what version of the zone file this is (serial: 1), and other things having to do with caching and secondary DNS servers. For the rest of the fields (refresh, retry, expire and minimum) use the numbers used here and you should be safe. Before the SOA comes a mandatory line, the $TTL 3D line. Put it in all your zone files.

Now restart your named (the command is ndc restart) and use dig to examine your handy work. -x asks for the inverse query:

$ dig -x 127.0.0.1

; <<>> DiG 8.2 <<>> -x
;; res options: init recurs defnam dnsrch
;; got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0
;; QUERY SECTION:
;; 1.0.0.127.in-addr.arpa, type = ANY, class = IN

;; ANSWER SECTION:
1.0.0.127.in-addr.arpa. 1D IN PTR localhost.

;; AUTHORITY SECTION:
0.0.127.in-addr.arpa. 1D IN NS ns.penguin.bv.

;; Total query time: 5 msec
;; FROM: lookfar to SERVER: default -- 127.0.0.1
;; WHEN: Sat Dec 16 01:13:48 2000
;; MSG SIZE sent: 40 rcvd: 110

So it manages to get localhost from 127.0.0.1, good. Now for our main task, the linux.bogus domain, insert a new 'zone' section in named.conf:

zone "linux.bogus" {
notify no;
type master;
file "pz/linux.bogus";
};


Note again the lack of ending `.' on the domain name in the named.conf file.

In the linux.bogus zone file we'll put some totally bogus data:

;
; Zone file for linux.bogus
;
; The full zone file
;
$TTL 3D
@ IN SOA ns.linux.bogus. hostmaster.linux.bogus. (
199802151 ; serial, todays date + todays serial #
8H ; refresh, seconds
2H ; retry, seconds
4W ; expire, seconds
1D ) ; minimum, seconds
;
NS ns ; Inet Address of name server
MX 10 mail.linux.bogus ; Primary Mail Exchanger
MX 20 mail.friend.bogus. ; Secondary Mail Exchanger
;
localhost A 127.0.0.1
ns A 192.168.196.2
mail A 192.168.196.4


Two things must be noted about the SOA record. ns.linux.bogus must be a actual machine with an A record. It is not legal to have a CNAME record for the machine mentioned in the SOA record. Its name need not be `ns', it could be any legal host name. Next, hostmaster.linux.bogus should be read as hostmaster@linux.bogus. This should be a mail alias, or a mailbox, where the person(s) maintaining DNS should read mail frequently. Any mail regarding the domain will be sent to the address listed here. The name need not be `hostmaster', it can be your normal e-mail address, but the e-mail address `hostmaster' is often expected to work as well.

There is one new RR type in this file, the MX, or Mail eXchanger RR. It tells mail systems where to send mail that is addressed to someone@linux.bogus, namely to mail.linux.bogus or mail.friend.bogus. The number before each machine name is that MX RR's priority. The RR with the lowest number (10) is the one mail should be sent to if possible. If that fails the mail can be sent to one with a higher number, a secondary mail handler, i.e., mail.friend.bogus which has priority 20 here.

Restart named by running ndc restart. Examine the results with dig:

$ dig any linux.bogus +pfmin

;; res options: init recurs defnam dnsrch
;; got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23499
;; QUERY: 1, ANSWER: 4, AUTHORITY: 1, ADDITIONAL: 1
;; QUERY SECTION:
;; linux.bogus, type = ANY, class = IN

;; ANSWER SECTION:
linux.bogus. 3D IN MX 10 mail.linux.bogus.linux.bogus.
linux.bogus. 3D IN MX 20 mail.friend.bogus.
linux.bogus. 3D IN NS ns.linux.bogus.
linux.bogus. 3D IN SOA ns.linux.bogus. hostmaster.linux.bogus. (
199802151 ; serial
8H ; refresh
2H ; retry
4W ; expiry
1D ) ; minimum


Upon careful examination you will discover a bug. The line

linux.bogus. 3D IN MX 10 mail.linux.bogus.linux.bogus.

is all wrong. It should be

linux.bogus. 3D IN MX 10 mail.linux.bogus.

This was done deliberately to illustrate the use of the root '.' . Looking in the zone file we find this line:

MX 10 mail.linux.bogus ; Primary Mail Exchanger

It is missing a period. Or has a 'linux.bogus' too many. If a machine name does not end in a period in a zone file the origin is added to its end causing the double linux.bogus.linux.bogus. So either

MX 10 mail.linux.bogus. ; Primary Mail Exchanger

or

MX 10 mail ; Primary Mail Exchanger

is correct.

It must be stressed that in the named.conf file there should not be `.'s after the domain names. You have no idea how many times a `.' too many or few have fouled up things and confused people.

So having made my point here is the new zone file, with some extra information in it as well:

;
; Zone file for linux.bogus
;
; The full zone file
;
$TTL 3D
@ IN SOA ns.linux.bogus. hostmaster.linux.bogus. (
199802151 ; serial, todays date + todays serial #
8H ; refresh, seconds
2H ; retry, seconds
4W ; expire, seconds
1D ) ; minimum, seconds
;
TXT "Linux.Bogus, your DNS consultants"
NS ns ; Inet Address of name server
NS ns.friend.bogus.
MX 10 mail ; Primary Mail Exchanger
MX 20 mail.friend.bogus. ; Secondary Mail Exchanger

localhost A 127.0.0.1

gw A 192.168.196.1
HINFO "Cisco" "IOS"
TXT "The router"

ns A 192.168.196.2
MX 10 mail
MX 20 mail.friend.bogus.
HINFO "Pentium" "Linux 2.0"
www CNAME ns

donald A 192.168.196.3
MX 10 mail
MX 20 mail.friend.bogus.
HINFO "i486" "Linux 2.0"
TXT "DEK"

mail A 192.168.196.4
MX 10 mail
MX 20 mail.friend.bogus.
HINFO "386sx" "Linux 1.2"

ftp A 192.168.196.5
MX 10 mail
MX 20 mail.friend.bogus.
HINFO "P6" "Linux 2.1.86"


There are a number of new RRs here: HINFO (Host INFOrmation) has two parts; it's a good habit to quote each. The first part is the hardware or CPU on the machine, and the second part the software or OS on the machine. The machine called 'ns' has a Pentium CPU and runs Linux 2.0. CNAME (Canonical NAME) is a way to give each machine several names. So www is an alias for ns.

CNAME record usage is a bit controversial. But it's safe to follow the rule that a MX, CNAME or SOA record should never refer to a CNAME record, they should only refer to something with an A record, so it is inadvisable to have

foobar CNAME www ; NO!

but correct to have

foobar CNAME ns ; Yes!

It's also safe to assume that a CNAME is not a legal host name for an e-mail address: webmaster@www.linux.bogus is an illegal e-mail address given the setup above. You can expect quite a few mail administrators to enforce this rule even if it works for you. The way to avoid this is to use A records (and perhaps some others too, like a MX record) instead:

www A 192.168.196.2

Load the new database by running ndc reload, which causes named to read its files again.

$ dig linux.bogus axfr

; <<>> DiG 8.2 <<>> linux.bogus axfr
$ORIGIN linux.bogus.
@ 3D IN SOA ns hostmaster (
199802151 ; serial
8H ; refresh
2H ; retry
4W ; expiry
1D ) ; minimum

3D IN NS ns
3D IN NS ns.friend.bogus.
3D IN MX 10 mail
3D IN MX 20 mail.friend.bogus.
3D IN TXT "Linux.Bogus, your DNS consultants"
gw 3D IN TXT "The router"
3D IN HINFO "Cisco" "IOS"
3D IN A 192.168.196.1
localhost 3D IN A 127.0.0.1
mail 3D IN HINFO "386sx" "Linux 1.2"
3D IN MX 10 mail
3D IN MX 20 mail.friend.bogus.
3D IN A 192.168.196.4
www 3D IN CNAME ns
donald 3D IN TXT "DEK"
3D IN HINFO "i486" "Linux 2.0"
3D IN MX 10 mail
3D IN MX 20 mail.friend.bogus.
3D IN A 192.168.196.3
ns 3D IN HINFO "Pentium" "Linux 2.0"
3D IN MX 10 mail
3D IN MX 20 mail.friend.bogus.
3D IN A 192.168.196.2
ftp 3D IN HINFO "P6" "Linux 2.1.86"
3D IN MX 10 mail
3D IN MX 20 mail.friend.bogus.
3D IN A 192.168.196.5
@ 3D IN SOA ns hostmaster (
199802151 ; serial
8H ; refresh
2H ; retry
4W ; expiry
1D ) ; minimum

;; Received 29 answers (29 records).
;; FROM: lookfar to SERVER: 127.0.0.1
;; WHEN: Sat Dec 16 01:35:05 2000

That's good. As you see it looks a lot like the zone file itself. Let's check what it says for www alone:

$ dig www.linux.bogus +pfmin
;; res options: init recurs defnam dnsrch
;; got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27345
;; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 1
;; QUERY SECTION:
;; www.linux.bogus, type = A, class = IN

;; ANSWER SECTION:
www.linux.bogus. 3D IN CNAME ns.linux.bogus.
ns.linux.bogus. 3D IN A 192.168.196.2


In other words, the real name of www.linux.bogus is ns.linux.bogus, and it gives you some of the information it has about ns as well, enough to connect to it if you were a program.

Now we're halfway.

5.7 The reverse zone

Now programs can convert the names in linux.bogus to addresses which they can connect to. But also required is a reverse zone, one making DNS able to convert from an address to a name. This name is used by a lot of servers of different kinds (FTP, IRC, WWW and others) to decide if they want to talk to you or not, and if so, maybe even how much priority you should be given. For full access to all services on the Internet a reverse zone is required.

Put this in named.conf:

zone "196.168.192.in-addr.arpa" {
notify no;
type master;
file "pz/192.168.196";
};


This is exactly as with the 0.0.127.in-addr.arpa, and the contents are similar:

$TTL 3D
@ IN SOA ns.linux.bogus. hostmaster.linux.bogus. (
199802151 ; Serial, todays date + todays serial
8H ; Refresh
2H ; Retry
4W ; Expire
1D) ; Minimum TTL
NS ns.linux.bogus.

1 PTR gw.linux.bogus.
2 PTR ns.linux.bogus.
3 PTR donald.linux.bogus.
4 PTR mail.linux.bogus.
5 PTR ftp.linux.bogus.

Now you restart your named (ndc restart) and examine your work with dig again:

$ dig -x 192.168.196.4 +pfmin

;; res options: init recurs defnam dnsrch
;; got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8764
;; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
;; QUERY SECTION:
;; 4.196.168.192.in-addr.arpa, type = ANY, class = IN

;; ANSWER SECTION:
4.196.168.192.in-addr.arpa. 3D IN PTR mail.linux.bogus.

so, it looks OK, dump the whole thing to examine that too:

$ dig -x 192.168.196 AXFR

; <<>> DiG 8.2 <<>> -x AXFR
$ORIGIN 196.168.192.in-addr.arpa.
@ 3D IN SOA ns.linux.bogus. hostmaster.linux.bogus. (
199802151 ; serial
8H ; refresh
2H ; retry
4W ; expiry
1D ) ; minimum

3D IN NS ns.linux.bogus.
4 3D IN PTR mail.linux.bogus.
2 3D IN PTR ns.linux.bogus.
5 3D IN PTR ftp.linux.bogus.
3 3D IN PTR donald.linux.bogus.
1 3D IN PTR gw.linux.bogus.
@ 3D IN SOA ns.linux.bogus. hostmaster.linux.bogus. (
199802151 ; serial
8H ; refresh
2H ; retry
4W ; expiry
1D ) ; minimum

;; Received 8 answers (8 records).
;; FROM: lookfar to SERVER: 127.0.0.1
;; WHEN: Sat Dec 16 01:44:03 2000

Looks good! If your output didn't look like that look for error-messages in your syslog, Do a

$ tail -f /var/log/messages

and check the resultant output.

5.8 Slave servers

Once you have set up your zones correctly on the master servers you need to set up at least one slave server. Slave servers are needed for robustness. If your master goes down the people out there on the net will still be able to get information about your domain from the slave. A slave should be as long away from you as possible. Your master and slave should share as few as possible of these: Power supply, LAN, ISP, city and country. If all of these things are different for your master and slave you've found a really good slave.

A slave is simply a nameserver that copies zone files from a master. You set it up like this:

zone "linux.bogus" {
type slave;
file "sz/linux.bogus";
masters { 192.168.196.2; };
};

A mechanism called zone-transfer is used to copy the data. The zone transfer is controlled by your SOA record:

@ IN SOA ns.linux.bogus. hostmaster.linux.bogus. (
199802151 ; serial, todays date + todays serial #
8H ; refresh, seconds
2H ; retry, seconds
4W ; expire, seconds
1D ) ; minimum, seconds


A zone is only transferred if the serial number on the master is larger than on the slave. Every refresh interval the slave will check if the master has been updated. If the check fails (because the master is unavailable) it will retry the check every retry interval. If it continues to fail as long as the expire interval the slave will remove the zone from it's filesystem and no longer be a server for it.