Benedikt Stockebrand
Diplom-Informatiker
Contact and Legalese
Terms and Conditions
DeutschDeutsch

Configuring a Name Server with BIND 4

This note deals with the basics of the somewhat tedious configuration of BIND version 4 (aka. named), the most popular Un*x DNS server. It only covers the basics; there are plenty details left out. Check out your man page if you need them.

I assume that you're somewhat familiar with the concepts of DNS. If you're not, check out some more introductory material, like The UNIX System Managers Manual, Chapter 10 from the BSD 4.4 documentation, W. Richard Stevens, TCP/IP Illustrated, Vol. I, Ch. 14 or Craig Hunt, TCP/IP Network Administration or your local named man page.

This note omits the features of the more recent BIND version 8, which heavily differs in the boot file syntax. Up to today many systems are still shipped with a BIND 4 by default, so we focus on it. A description of BIND 8 is bound to come up some time soon, though.

Dealing with the Server

The named server is always run as a stand-alone server. The most important command-line options are:
-d [n]
Enable debugging. If n is specified set the debugging level to n.
-b file
Specify an alternate boot file.
-q
Trace all incoming queries.

To manipulate a running server you may send it these signals:

HUP
Reload the boot file (esp. useful with primary servers).
INT
Dump the current data base and cache to /var/tmp/named_dump.db or a similar place.
USR1
Increment the debug level.
USR2
Set the debug level back to zero.
WINCH
Toggle tracing of all incoming queries. Watch the size of your syslog output.
IOT
Append statistics to /var/tmp/named.stats or wherever your named feels comfortable to dump its statistics. These stats are appended to the file.

Configuration Tools

The configuration syntax of named is somewhat cryptic, especially as far a the zone files are concerned. There's a preliminary version of a tool called dnsconfig available from us. It's a fairly simple Perl script (requiring Perl 5) that takes care about keeping forward and reverse maps consistent and generally provides a less tedious configuration syntax. It generates forward and reverse zone files plus boot files for all servers involved.

If you're going to start a named configuration from scratch this may be the easiest way to go.

Named Configuration "Boot File"

The BIND server named reads its configuration data from the boot file, usually /etc/named.boot or /etc/namedb/named.boot or wherever your Un*x places it.

Comments in the config file start with a semicolon, not a hash mark. There are no line continuations available.

Here's a basic sample boot file as a starting point for your own boot file.

The directory Directive

The first thing you usually do in a boot file is to specify the directory where all subsequent files are stored. This is done using the
directory <directory name>
directive. By convention, primary servers keep their files in /etc or /etc/named or /etc/namedb or such while secondary servers keep them in /var/named or the like.

Caching Servers

The most common servers are caching servers. You should almost always run a caching server in your local network to reduce your outbound DNS traffic, both to reduce the traffic itself and to speed up lookups.

By default all servers provide a cache. By default this cache is only used for data requested from child zones on behalf of a client. If you want to disable this you use the

option no-recursion
option.

To set up a caching server for zones outside it's own control you need to set it up explicitly, though. There are two ways to set up such a caching server. The traditional way initializes the cache with entries for the root servers and uses them to do assorted lookups. This however is generally considered a bad idea by now, except by named which keeps buggering syslog about missing name servers for the root domain whenever it is restarted. In (well, almost) any case you better use the name server of your uplink ISP so it can cache results returned from the root domain servers. Use the

forwarders <forwarding servers...>
directive to specify your ISPs name server(s) and
option forward-only
to make sure you only use their name servers and don't fall back to any root domain servers. If you really have any reason to access the root servers directly you shouldn't need to read this note.

Cache Initialization

Usually it may be necessary to prime your name server cache with some data, especially about name servers for the root domain (so named stops complaining). To do so you use a
cache <domain> <initial file>
directive. The <domain> usually specified here is ".", which stands for the root domain. The <initial file> is used to initialize the cache. It is not used as the storage place for cached lookups! In this file you place all the entries necessary to get your name server up and running. People used to put the root domain server addresses here so they could be used for lookups. In fact there's a FTPable file available somewhere that contains exactly these root domain servers. But if you're just using a forwarding-only server as suggested above you might as well use the (possibly somewhat out-of-date) file coming with the BIND distribution.

Secondary Servers

In many cases you'll want to configure a secondary name server for a domain. The syntax is
secondary <domain> <servers...> <zone file>
The domain may be either a forward or reverse lookup domain. Reverse lookup domains are specified using the IN-ADDR.ARPA pseudo-domain. The network 192.168.41.0/24 is named 41.168.192.IN-ADDR.ARPA. Aside from the fact that this syntax doesn't support netmasks that don't match a byte/octet boundary it has a certain tendency to cause all sorts of hard-to-find bugs. Be especially careful here.

The <servers...> are a list of primary servers for that zone. The secondary loads the zone files from there via a zone transfer and stores them in the <zone file>. Usually only a single primary server is specified.

Primary Servers

To configure your named as a primary name server for a domain you use a
primary <domain> <zone file>
directive. It is pretty much like a secondary directive except that there are no primary servers specified and the zone file is stored in the specified file. See the Zone Files section to learn about writing a zone file.

Serving Multiple Zones/Domains

Making a single named serve simultaneously as a primary, secondary and/or caching-only server for different domains/zones is common practice. Just use multiple server directives in your boot file.

In most cases you'll configure your server for both forward and reverse lookups using multiple primary and/or secondary directives for both the forward and reverse lookup domains. There's one important thing you better don't forget: There's exactly one zone file for every zone.

In the "Security Issues" section you'll find some additional directives and options primarily useful in secured systems.

Useful Conventions

It is highly recommended to use the first host address in a network for the name server. All other services can be identified through a CNAME entry in the DNS data base but if you ever need to figure out the IP address of the local name server that's on another address you'll appreciate this convention.

Keeping primary server zone files in /etc is a Good Thing® because these zone files are considered configuration files. With secondary and cache servers the preferred place is usually somewhere in /var because their files are volatile and taken from another source.

Zone Files

Unless you're building a primary server you're already done now. If however you need to build a primary server you have to write a "zone file" for every zone you want to provide name service information for. This is where things really get messy, especially since the syntax is occasionally causing some confusion.

Sample Files

You'll find a reverse zone file for the 127.0.0 reverse map here. Just change the primary name server and mail address in the SOA record there before you use with your system. As a (reasonable) alternative you may prefer to provide an entry for localhost in your /etc/hosts file. Don't forget to add a localhost.your.dom.ain entry to all your forward maps if you don't use an /etc/hosts entry.

There are also sample maps for the example.com domain and its reverse map for the 192.168.47 network. These should provide a decent starting point for your own zone files.

Convenience Statements

There are two convenience statements. They are
$ORIGIN <domain>
to make all relative names relative to <domain> and
$INCLUDE <filename> [<domain>]
to include a file and optionally to make all its entries relative to the origin <domain>.

Both statements must start in the first column.

Resource Record ("RR") Statements

All remaining statements are resource record statements. They make for the majority of a zone file.

Field Formats

One of the most annoying misfeatures of BIND is to keep its configuration syntax very close to the DNS data format. Here's that syntax:

  Normal Syntax BIND Syntax Notes
Root Domain --- . You don't need this outside DNS
FQDN www.example.com www.example.com. Note the trailing period.
Current Origin --- @ See $ORIGIN
Relative host name www www Identified by a missing trailing dot, always relative to @
Mail Address root@example.com root.example.com. "@" turned into a period, trailing period.
IP Address for reverse maps 192.168.47.11 11.47.168.192.IN-ADDR.ARPA. IP addresses are put in a special pseudo domain

General Resource Record Format

The resource record syntax is always
[<name>] [<ttl>] <address class> <type> <resource record data>
The <name> field must start in the first column (COBOL programmers cheer up). It provides the "key" value for the record defined in the statement. If it is omitted the value of the previous record is used.

The <ttl> field specifies the time that a value is cached. It is usually omitted so that the default value from the SOA record applies.

The <address class> field is always set to IN for the Internet address class. The only other address class at least partially supported is MIT/Athena "Hesiod" (HS).

The <type> field specifies the type of record defined in the statement. It is followed by the <resource record data> field which holds some data in a format specific to that record type.

SOA Records

Every zone file contains exactly one SOA ("Start Of Authority") record, by convention the very first record in a zone file. Here's a typical example:
      @    IN    SOA  dns1.example.com. dnsadmin.example.com. (
                 1998072001 ; Serial
                 10800      ; Refresh (3 hours)
                 1800       ; Retry   (3 minutes)  
                 2592000    ; Expire  (30 days)
                 259200     ; Minimum (3 days)
                 )
    
The <name> field is usually "@", the origin. The <ttl> field is usually omitted.

The <resource record data> field consists of the FQDN of the primary server for that zone, the e-mail address of the person in charge and a parenthesized vector of five positive integers.

The first is a serial number that must be incremented whenever a zone file is updated---otherwise the secondary servers won't transfer that new zone file any time soon. It must be no more than 10 digits long. By convention this somehow encodes the date where the file was created, either as the example shows or using the number of seconds since the epoch. Incrementing this number is a very popular thing not to do during DNS configuration and always a fun thing to debug...

The second is a refresh interval in seconds. It specifies how often the secondary servers compare the serial number with the primary server to see if they have to start a zone transfer. The third number specifies the retry interval in seconds before a secondary server retries a failed zone transfer.

The fourth is the number of seconds after which a secondary server expires the zone file if the primary server is unreachable.

The fifth number is the minimum ttl value for all <ttl> fields of the resource records in this zone.

NS Records

A NS ("Name Server") record delegates a subzone to another name server. According to Internet specs every (sub)zone needs at least two servers, usually a primary and at least one secondary. These can be specified using NS records. The zone file should also contain a NS record for the "@" zone referring to the primary server. The name specified must be the canonical name of the server. Example:
@      IN  NS  dns             ; I (dns) am primary name server for @
silly  IN  NS  dns-silly       ; dns-silly.@ is name server for silly.@
silly  IN  NS  fallback-silly  ; and so is fallback-silly.@

A Records

An A ("Address") record maps a host name to an IP address. Note that in A Records the IP address is specified in the normal way, not as an address in the IN-ADDR.ARPA. pseudo domain, for example
gateway  IN  A  192.168.47.25
         IN  A  192.168.42.7
If a machine has multiple IP addresses there should be multiple entries as the example shows.

PTR Records

A PTR ("Pointer") record is used with reverse maps, mapping IP addresses to host names. Generally there should be corresponding pairs of A records in forward maps and PTR records in reverse maps. To continue our example with the first interface of the host gateway we need this PTR record in the reverse map for the 192.168.47.0 network
25  IN   PTR  gateway.example.com.
assuming that we've set the origin to "47.168.192.IN-ADDR.ARPA.".

MX Records

An MX ("Mail eXchanger") record specifies a mail server that is willing to accept mails coming in for the host named. Each MX is assigned a preference value which is a positive integer. The smaller the preference number the higher the preference of the MX.

The name specified with an MX record may contain an asterisk ("*") as a wildcard character to announce a mail exchanger for a whole domain. Watch your butt if you've got subdomains, though. Here comes an example:

;name                     preference   mail exchange server
nfs.example.com.  IN  MX  10           dns.example.com.
*.example.com.    IN  MX  20           mailgate.example.com.
*.example.com.    IN  MX  40           mailgate.example-isp.com.

CNAME Records

It is often convenient to assign additional "nicknames" to a machine. This is done through CNAME ("Canonical Name") records. If Mgmt decides our mail server must be named "mail" but we rather like to call it "biff" we do this:
biff  IN  CNAME  mail
Note however that in all other records you must not specify a nickname but the canonical name.

Useful Conventions

It is good habit to provide CNAME entries for all services you provide, like http, nntp, nfs etc. This will simplify moving services across machines especially if a lot of client machines use these services. Changing the DNS entries for your NFS server is definitely easier than rewriting the /etc/fstab or /etc/vfstab files or whatever of every single workstation in your system.

Providing MX records (or a single wildcard MX) for all your machines can save you from lots of trouble if a machine is temporarily down, especially if you tell that MX machine to be slow with the usual "Your mail has been delayed..." mails.

Finally, try to keep the forward and reverse maps in sync. Some security-conscious people will simply disallow connections from IP addresses that don't have a matching reverse map. And life would be much easier for everyone except spammers if all mail servers were checking the HELO line of every incoming message against the remote IP address using this feature.

Security Issues

Finally, here are some additional topics relevant mostly in a security-sensitive context only.

Security-Related Boot File Directives and Options

Logging

The most important thing in security world is proper auditing, in this case logging of all queries. This can be enabled through the
option query-log
option. Prepare for large log files, though.

Syntactic Validation

Another Good Thing® is to check that query results are valid according to the RFC 952 spec. This protects your system from bad zone files on your primary and/or secondary servers and, what's more important, from attacks using ill-formatted responses. To do so you use the check-names directive:
check-names primary ignore
check-names secondary warn
check-names response fail
The name checking can be configured individually for primary and secondary zone files and responses stored in the cache. It can be turned off using the ignore keyword, logged but still used using the warn keyword or not used at all (which is probably best to do with caching servers) with the fail keyword.

Zone Transfer Restrictions

To avoid attackers to download your whole zone file to pick targets easily you may want to restrict zone transfers to certain hosts or networks. To do so you use the
xfrnets <server or network addresses...>
directive. It limits zone transfers to the servers and/or networks specified.

Non-Recursive Servers

In the past there have been DNS-based spoofing attacks that corrupted authoritative name servers through their cache. Since authoritative servers usually cache their child zones it may be reasonable to stop these cache poisoning attacks by referring a query for a child zone record to an authoritative server for that zone. To do so you use the
option no-recursion
option. This may also be reasonable for performance reasons. But then again, if you need to worry about DNS performance you shouldn't be reading this note.

Zone Files

Providing accurate HINFO records for your machines is considered a potential security problem. It gives a potential attacker valuable clues about your machine. As a consequence, don't provide HINFO records for your machines. They're mostly obsolete exactly due to this problem anyway.

Similar considerations hold for the even more obsolete WKS (aka. Well Known Services) record type.

Split Horizon Configurations

In some cases you may want to keep some of your machines visible only to a limited set of machines, usually those in your local, trusted net. To do so you usually run two primary name servers for your domain, one visible itself only to your local net to provide the full data and another visible to the outside to show only the machines everyone else is allowed to see. While such a setup is well beyond the scope of this note, here are some clues:
  • Block access to your internal server from the outside in your packet filter.
  • Make an external server a caching DNS server. This may be your "publicly visible" name server or any other visible machine.
  • Make the internal server do all its lookups through that external server (through the forward-only option).

Conclusion

Admittedly, configuring a name server, especially a primary one, is a major pain in the behind. The syntax is too closely based on the DNS protocol to be easily readable or writable and having to use an individual file for every zone in question is a major nuisance. So is the necessity to keep forward and reverse mapping in sync.

© 2003—2013 Benedikt Stockebrand[2013-12-20 14:25:52 UTC]