Previous Next

Home Up


BIND DNS server setup

Contents

  1. File names
  2. Basic caching nameserver
  3. Adding entries for static IP addresses
  4. Going straight to the roots
  5. Adding a pseudo-domain for private IP addresses
  6. Types of DNS records

Most basic systems use the hosts file for name-to-address translation for local machines, and DNS only for machines that are not in the hosts file. At times, it's more useful to actually have a DNS server running locally and use it first, falling back to the hosts file only when DNS is not running. The most common reasons are:

Most people will be interested in the caching aspect. In this case, the nameserver doesn't actually handle any domains itself, but passes all queries on to XMission's name servers to handle. What it does do is cache the results of those queries locally, so that the next time that same name is queried it can return the result immediately without having to talk to XMission's name servers. If you're on a slow modem link, this can make a fair amount of difference.

The ultimate reference on BIND and DNS in general is the cricket book, "DNS and BIND" from O'Reilly. If you are serious about DNS, I would suggest getting the 2nd edition of this book. It contains an excellent tutorial on DNS as well as technical reference material.

RedHat 6.2 ships with BIND version 8 as the default nameserver software, so no updates need downloaded. If future updates occur, you should be able to download the updated source RPMs from Metalab and build them.

File naming conventions

There is a pattern to the naming of the BIND configuration files I set up. These files reside in /var/named on RedHat systems. The conventions I use are:

named8.boot The initial configuration file for BIND version 8 that describes what zones it should handle and what files the rest of the configuration data is in. It will wind up as /etc/named.conf, I keep an extra copy in /var/named for safety.
db.cache The initial hints file containing the NS and A records for the root nameservers. The cache part of the name is a historical artifact, dating back to the first pieces of software that implemented DNS.
db.domain Files like this contain the records for a particular domain. Sometimes the suffix may be omitted. For example, I would store the records for xmission.com in a file called db.xmission.com or db.xmission.
db.IP-network-number These files contain the reverse-DNS records ( used to turn IP addresses into host names ) for an IP network. IP-network-number is replaced by the IP network number for the network. The records for the 192.168.171.x class C network would thus be stored in a file called db.192.168.171. Note that trailing 0's are omitted in from the filename.
db.IP-address A special case of the previous one. In some cases you might need to make an entry for exactly one IP address, for example if you have a static IP address from XMission and want your nameserver to be able to resolve it when you are not dialed in. In this case you use the complete IP address in the filename, for example db.207.135.128.211 contains the single entry for the static IP address for tknarr.users.xmission.com.

Basic caching nameserver

One of RedHat's packages is called caching-nameserver. The following will severely interfere with this package by changing almost every file it deals with.

The first thing to do is get the file containing the list of root nameservers. This initial cache or hints file can be obtained via FTP from the Internic. I will not make a local copy available, you should go directly there. You will need to place this file in /var/named. I usually name this file db.cache You should check back on the FTP site every few months and make sure the file hasn't changed. If it has changed, you'll need to download it again, put in in place and restart the nameserver. If you do not have this file, BIND will not work or not work correctly.

The next thing to do is to edit the named configuration file. I normally do my work in /var/named, calling the file named8.boot, and then when I'm ready to test I copy /var/named/named8.boot to /etc/named.conf where BIND expects to find it. You can get the file here and save it as /var/named/named8.boot. It should look like this:

options {
        directory       "/var/named";
        query-source    address * port 53;

        forward         only;
        forwarders {
                198.60.22.2;
                198.60.22.22;
        };

        allow-query {
                localhost;
        };
        allow-transfer {
                localhost;
        };
        
        check-names     master          warn;
        check-names     slave           warn;
        check-names     response        warn;

};

zone "." in {
        type            hint;
        file            "db.cache";
};

zone "127.in-addr.arpa" in {
        type            master;
        file            "db.127";
};
zone "localhost" in {
        type            master;
        file            "db.localhost";
};

The options block controls how BIND will operate. The directory entry tells it that it can find it's zone and other data files in the /var/named directory, which is a standard location. The query-source line tells it to send queries originating from the standard DNS port, which makes firewall handling much easier. The forward and forwarders sections tell it that it is not to attempt to follow DNS queries by itself, but that it should merely forward any queries it cannot answer to XMission's name servers and let them deal with it. This is the easiest way of handling things, since a) it takes advantage of the caches on XMission's name servers as well and b) it eliminates the need for you to personally keep track of the root name servers and changes in them. The allow-query and allow-transfer instruct BIND to only allow the local machine to do queries and zone transfers, and to reject any attempt by anyone else to use your nameserver. This isn't particularly important at the start, but locking everyone else out prevents some nasty security holes and can keep you from looking like a fool later on. Note that the use of localhost in these options is not referring to the machine localhost. As used here, localhost is a special ACL keyword translating to "any address assigned to an active network interface on the local machine". This means that this one keyword will cover all the addresses you might assign to the machine, so you don't have to worry about adding additional entries as you add network interfaces and addresses. On a single machine, this keyword is all that's needed. The check-names entries simply make BIND log warnings about host names that are acceptable to BIND but illegal per the relevant RFCs.

One decision you can make involves the forward line. As it appears here, it tells BIND to only forward queries. If BIND cannot resolve the name out of the local zone data, it forwards the query to XMission's nameservers and lets them resolve it. If it cannot contact XMission's servers, then names outside your local machine cannot be resolved at all. If you change the only keyword on the forward line to first, BIND will attempt to forward the queries to XMission's servers first. If it cannot contact them, it will attempt to contact the Internet root nameservers directly and resolve the name itself. This is a sort of compromise, taking advantage of XMission's nameserver cache most of the time while still letting you operate in the unlikely event that both of XMission's nameservers are down. To me it boils down to whether or not you keep the db.cache file up to date. If you do, forward first will work all the time. If you don't, forward only is safer as it will prevent you from using out-of-date root nameservers.

The zone blocks actually indicate portions of the namespace for which this nameserver knows answers. What we have here says that it knows about the "localhost" name for your local machine, and the 127.x.x.x network block which is used for local loopback. These zones are vanilla across almost every nameserver, and the db.127 and db.localhost files should be downloaded and placed in /var/named where the nameserver can find them. Do make sure they're readable by everyone when you do this. Note that db.localhost contains an MX record for localhost. Without this mail addresses of the form username@localhost are technically illegal, since no machine handles mail for localhost. Most mail systems will attempt to go ahead and deliver mail to localhost directly anyway, but I'm picky about conforming to the standards. Other than that the only thing these zone files contain are the name-to-address and address-to-name records that make localhost equal to address 127.0.0.1 and vice versa.

The next step is to update the resolver configuration. You need to edit three files to do this: /etc/resolv.conf, /etc/nsswitch.conf and /etc/host.conf.

/etc/resolv.conf is easy. You simply need to edit it to contain only the line "nameserver 127.0.0.1". This tells the resolver routines to contact the nameserver on the local machine instead of going straight to XMission's nameservers.

/etc/nsswitch.conf is the name service switch configuration file for glibc. You need to locate the line it that starts with hosts. RedHat sets it up by default to be files first, DNS only if the file lookup fails. You want to switch the order of the dns and files keywords so that dns comes first and files last. Also while you're in here, I recommend that you remove all the nis, yp, nisplus and nis+ keywords from all lines except the netgroup and publickey lines. This will disable use of NIS for name lookup. NIS does not live well together with DNS, I'm afraid, and it's not something you want running unless you need it for NFS or a Sun network.

/etc/host.conf is the old configuration file for the libc5 resolver routines. If it doesn't exist, you need to create it. Then make it contain only the single line "order bind, hosts". This will make sure that older programs linked against libc5 use the nameserver first and the hosts file only if the nameserver is not running or doesn't know the name.

Now, we need a patch to the startup script to start named in the appropriate runlevels. Download the patch file into the /tmp directory. Then cd to /etc/rc.d/init.d and do 'patch <named-init.patch' to update the init script. You can delete the named-init.patch file and the named.orig file left behind by patch once you are done. Then make sure things are correct by doing 'chkconfig named reset'.

The next step is to try turning on the nameserver and seeing if it works. To turn it one manually, do a "cd /etc/rc.d/init.d" and then "./named start". It should start with no error messages. Then issue the following commands:

    host localhost.
    host 127.0.0.1
    ping localhost
The dot after localhost on the first command is significant and cannot be omitted. You should get the expected address and name responses back from the first two almost immediately, and be able to ping the local machine with no problem. Success here indicates that the software is working properly. If these commands fail, shut off the nameserver with "./named stop" and make sure you installed the configuration and zone files in the proper places.

If everything worked up to now, dial in to XMission and try looking up several host names using the host command again. You should get responses fairly quickly on valid host names. Also, if you look up a name more than once, the second and subsequent responses should be very quick since they come out of the local cache instead of from XMission's servers.

If all is well so far, you can make the nameserver permanent. To do this, first do a "cd /etc/rc.d". Then issue the following commands:

    chkconfig --levels 345 named on
    chkconfig --levels 0126 named off
This will set up the proper start script links so that BIND is started in run levels 3, 4 and 5 and stopped on system shutdown. You won't need to reboot or anything after this.

Adding entries for static IP addresses

One interesting property of the BIND program is that a zone containing only a single machine is entirely legal. This lets you add true DNS entries on a local nameserver for single static IP addresses without interfering with the lookup of any other xmission.com name or address. This requires adding two zone files and two zone entries in named.conf: one for the name-to-address record, one for the address-to-name record. The files that follow are suitable for use with XMission static IP accounts.

First, we need the config file zone entries. They look like this:

zone "myusername.users.xmission.com" in {
        type            master;
        file            "db.myusername";
};
zone "999.999.999.999.in-addr.arpa" in {
        type            master;
        file            "db.999.999.999.999";
};

Substitute your XMission username for myusername and the static IP address XMission assigned you for 999.999.999.999 and put these zone sections into named.conf below the ones that are already there. Order doesn't matter for zone sections.

Now we need zone files for these two entries. First is the db.myusername file containing the name-to-address records:

@               IN SOA          myusername.users.xmission.com. root.myusername.users.xmission.com. (
                                        1999010101      ; Serial
                                        10800           ; Refresh every 3 hours
                                        3600            ; Retry after 1 hour
                                        604800          ; Expire after 1 week
                                        86400           ; Minimum TTL 1 day
                                )
                IN NS           myusername.users.xmission.com.

;
; Host addresses
;
@               IN A    999.999.999.999

;
; Mail exchange records
;
@               IN MX   100 myusername.users.xmission.com.

Then the db.999.999.999.999 file containing the records that map from an IP address back to a hostname:

@               IN SOA          myusername.users.xmission.com. root.myusername.users.xmission.com. (
                                        1999010101      ; Serial
                                        10800           ; Refresh every 3 hours
                                        3600            ; Retry after 1 hour
                                        604800          ; Expire after 1 week
                                        86400           ; Minimum TTL 1 day
                                )
                IN NS           myusername.users.xmission.com.

@               IN PTR  myusername.users.xmission.com.

Edit these files, replacing myusername with your XMission username and 999.999.999.999 with your XMission-assigned static IP address. Also, the second line of each file is a DNS serial number. By convention, this is usually the date the file was lasted edited, packed into the form YYYYMMDDSS, that is the 4-digit year, the 2-digit month, the 2-digit day and a 2-digit sequence number in case you make multiple changes on a single day. The exact format isn't critical, except that the number should increase each time a change is made. Getting this right isn't critical for a single machine, but doing it right from the start makes things easier. I have both files set for serial numbers of 1999010101, that is the first edit on 1-Jan-1999, which should be fine for most purposes, but I would suggest that you edit them to reflect the date you downloaded the files.

Save the files in /var/named as db.myusername and db.999.999.999.999, again substituting your XMission username and static IP address for the boldfaced parts.

Once you have the zone files safely saved and the entries added to named.conf, you can start or restart the nameserver. If it wasn't running before, it'll get the new additions when you start it. If it was running, you can use the ndc program to force it to re-read it's configuration by issuing the "/usr/sbin/ndc reload" command. You'll need to be root to do this. Once you've done that, make sure you aren't dialed in and use the host command to check that your hostname and static IP address can be looked up properly.

Going straight to the roots

Most dial-up users will want to have BIND operating solely as a cache for name lookups, defering real lookups to XMission's servers. Sometimes, though, it's useful to have a real nameserver set up that does lookups straight into the Internet's domain name system. This used to involve some changes. With version 8.2 of BIND, however, the only change involves the forward and forwarders lines.

Before you do this, remember that there's some responsibility that comes with this. First and foremost, you will need to check back with Internic every month or so and get a new copy of the root nameserver cache file if it's been updated. Second, if you have zone files that contain any private IP addresses or unregistered domains, you must set up the allow-query and allow-transfer entries in appropriate places to prevent anyone in the outside world from every seeing those IP addresses and domains. If you have no registered domains this is easy since nobody from the outside should be allowed to query your nameserver at all. If you have a registered domain and your nameserver is one outsiders should legitimately contact, you're well beyond what's described here. If you haven't got it already, I would recommend that you get the O'Reilly cricket book ( "DNS and BIND" ) and read it thoroughly.

The first thing to do is get the file containing the list of root nameservers. This initial cache or hints file can be obtained via FTP from the Internic. I will not make a local copy available, you should go directly there. You will need to place this file in /var/named. I usually name this file db.cache

Second, you will need to edit the named8.boot file. Locate the forward and forwarders lines, and delete them and the block of forwarders IP addresses. When done, it should look like this:

options {
        directory       "/var/named";

        allow-query {
                localhost;
        };
        allow-transfer {
                localhost;
        };
        
        check-names     master          warn;
        check-names     slave           warn;
        check-names     response        warn;

};

zone "." in {
        type            hint;
        file            "db.cache";
};

zone "127.in-addr.arpa" in {
        type            master;
        file            "db.127";
};
zone "localhost" in {
        type            master;
        file            "db.localhost";
};

Install this file as /etc/named.conf, the rest of the setup is as for a caching nameserver. The nameserver process will now bypass XMission's nameservers entirely and resolve names using the Internet root nameservers directly.

Once you've installed these changes, you'll need to reload the nameserver process. The easiest way to do this is by using the "/usr/sbin/ndc reload" command. Once this is done, use the host command to verify that name lookups are working, and check /var/log/messages for error messages if anything doesn't work right. You will get a complaint if you start BIND while not dialed in, but lookups of localhost and 127.0.0.1 should work fine and BIND will just retry the roots when you start doing lookups after dialing in so you can safely ignore messages about "can't find root nameservers" when not dialed in.

The decision to use a real nameserver rather than a caching one is fairly small, but one you should think about. A caching nameserver as set up in the first section takes advantage of the fact that XMission's servers also cache DNS queries, and will typically have a large cache filled with answers to queries generated by the entire XMission network. Lookups will often be quicker because the answers are already in XMission's server's caches and they won't have to chase them down across the entire Internet, and you get to avoid having to correctly configure the root nameservers. OTOH, using the roots directly can keep you from inheriting ( thankfully rare ) problems with XMission's DNS servers, and can be neccesary if you have a registered domain. I'd generally stick with a caching nameserver unless you have a specific technical reason to do otherwise.

Adding a pseudo-domain for private IP addresses

If you've got several computers and are using private IP addresses for them, they all need hostnames. The usual way to do this is to put the names in the hosts file on each computer, but if you're using BIND you might wonder if you could put them straight into DNS. The answer is yes, with one caveat: you need to make sure that the names you pick do not exist in the real DNS system. The easiest way I've found to do that is to pick a top-level domain ( TLD ) that isn't in use. In the real DNS, TLDs are of two general forms:

I don't know of any plans to use single-letter TLDs, so a safe bet is to pick a letter you like and use it as a TLD. In the examples here I'll use .z as the TLD. Then pick a domain name you like for use as a second-level domain ( 2LD ), for example xyzzy.z. In the following examples I'll use xyzzy.z as the domain name and 192.168.15 as the private IP network. Substitute your choices for these values in the examples and files.

First we need a zone file for the domain. We'll call it db.xyzzy, and it should look something like this:

@               IN SOA          host1.xyzzy.z. myusername.host1.xyzzy.z. (
                                        1999010101      ; Serial
                                        10800           ; Refresh every 3 hours
                                        3600            ; Retry after 1 hour
                                        604800          ; Expire after 1 week
                                        86400           ; Minimum TTL 1 day
                                )
                IN NS           host1.xyzzy.z.

;
; Host addresses
;
host1           IN A            192.168.15.1

;
; Mail exchange records
;
host1                   IN MX   100 host1.xyzzy.z.

;
; Network pseudo-address for mailers
;
xyzzy.z.                IN A    192.168.15.1

;
; Network numbers
;
xyzzy-net               IN PTR  0.15.168.192.in-addr.arpa.
xyzzy-net               IN A    192.168.15.0

You can add additional A and MX records for additional hosts, if you have more than one machine.

The next thing we need is a zone file for the IP network. We'll call it db.192.168.15, and it should look like this:

@               IN SOA          host1.xyzzy.z. myusername.host1.xyzzy.z. (
					1999010101	; Serial
					10800		; Refresh every 3 hours
					3600		; Retry after 1 hour
					604800		; Expire after 1 week
					86400		; Minimum TTL 1 day
				)
		IN NS		host1.xyzzy.z.

;
; Addresses point to canonical names
;
1		IN PTR		host1.xyzzy.z.

;
; Network name and subnet records
0               IN PTR	xyzzy-net.xyzzy.z.

As with the domain zone, you can add additional PTR records for additional hosts.

The final step is to modify the BIND configuration file to refer to the new zone and have BIND reload it's configuration. If you have saved the two files in /var/named under the names I used, you can add the following stanzas to the end of /var/named/named8.boot:

zone "xyzzy.z" in {
        type            master;
        file            "db.xyzzy";
};
zone "15.168.192.in-addr.arpa" in {
        type            master;
        file            "db.192.168.15";
};

Remember to substitute your chosen domain name and IP network for xyzzy.z and 192.168.15 in the file. Copy /var/named/named8.boot to /etc/named.conf and issue the "/usr/sbin/ndc reload" command to signal BIND to reload it's configuration. Any error messages from BIND will appear in /var/log/messages. You should test your configuration by using the host command to look up various hostnames and IP addresses that you have put in the new zone files.

Types of DNS records

There are a fairly large number of records that can occur in the DNS system, but only a few types are commonly used. The most common types are:

SOA records - start-of-authority records mark the beginning of a DNS zone. Most of the fields in this record are commented in the zone files I gave above, and the values I give for them are fairly standard. Three fields aren't:

The second and third in this list are mainly used for troubleshooting, when someone else has a problem with your DNS data and needs to get in contact with the person responsible for it.

The Serial field is a serial number for the zone, and is used by BIND to decide whether the data in the zone file has been changed since it last loaded it. I use a relatively standard format for my serial numbers, which is the date the data was last modified plus a sequence number for multiple modifications on the same day:

NS records - these provide links to the name servers for the zone data. The are of the form:

        IN NS nameserver-name
These records are what are referred to as "glue records", since they hold the DNS system together and allow a query to start at the root name servers and work it's way down to the actual name server that has the requested data. Note two things about these records:

Normally you won't have to deal with the other half of glue records, since they only come into play when you have to delegate part of your namespace to someone else. If you're running a single domain as a single zone ( the most common situation ), you won't need to worry about this other than to insure that the NS and A records are in your zone files. If you're delegating domains, I suggest you get the cricket book ( mentioned at the top of this page ) and read and understand all of it before you do anything else.

A records - these records provide the mapping from a host name to an IP address, and occur in the zone file associated with the domain name. They have the form:

hostname    IN A ip-address
Usually you omit the domain name from the hostname, allowing BIND to pick up the domain name automatically from the domain for the zone file. Thus, if the zone stanza for a zone file said "xyzzy.z" and you had an A record like:
www         IN A 192.168.15.5
it would assign IP address 192.168.15.5 to host www.xyzzy.z. This can be very useful if you have to change domains, since the domain name will automatically change once you change the zone stanza and you won't need to edit much in the zone file. On occasion one needs to explicitly specify a domain, in which case the full name including the domain should be terminated with a period ( '.' ) to tell BIND that it should not append the zone file's domain to the name.

PTR records - these records map from IP addresses to host names, and occur in a zone file associated with the IP network number. They have the form:

ip-address   IN PTR hostname
Again, the IP address is normally only the trailing octet value ( for a class C network ) with the leading parts picked up from the zone this file is for. IP addresses in these records are expressed in a special form, created by reversing the IP address octets and appending .in-addr.arpa to them. Thus, the IP address 192.168.15.75 would be expressed as 75.15.168.192.in-addr.arpa. Hostnames are almost always fully-specified names ending in a period, since the domain for the zone file is an in-addr.arpa one and not the normal DNS domain you're used to seeing.

MX records - these records are used by the mail system to decide what machine to deliver mail to. They have the form:

hostname    IN MX priority mailserver
When the mail system needs to deliver mail, it takes the hostname to the right of the @-sign in the address and looks up the MX records for it. The records are sorted by priority, and the mail system attempts to deliver the mail to the mailserver named in the MX record with the lowest priority value. If that machine is unavailable, it tries the next-lowest, and so on through the record with the largest priority value. If you have a record with a priority of 10 and one with a priority of 100, the priority 10 record will be tried first. Technically no machine lacking an MX record can have mail delivered to it, but most mail software looks up the A record if no MX record exists and tries to deliver mail directly.

Some less-commonly seen records include:

HINFO records - these contain information about the hardware and operating system for a particular machine.

WKS records - these contain information about the well-known services offered by a particular machine, such as Telnet and FTP servers, e-mail, news and DNS lookup. The original idea was that systems that wanted to connect to a service on a machine would first get the WKS record and see if it offered that service. The idea never really caught on, and WKS records are fairly uncommon.

RP records - these contain contact information for the person responsible for a given machine. Their purpose has been pretty much taken over by whois.

TXT records - these contain arbitrary text associated with a machine. Their most common use was in conjunction with RP records, and they are not often seen. A few specialized systems use TXT records to contain additional data about machines.


Previous Next

Home Up


tknarr@silverglass.org