This article originally appeared in the March 2003 issue of the Dæmon News Online Magazine. This is a cleaned-up version of the article with minor style edits and made it HTML5 compliant; else, the content has not been changed.
When working any network that uses TCP/IP, having host name resolution (typically DNS is really important for applications, but also to reduce the need to remember IP addresses. FreeBSD includes BIND (developed by ISC) to handle DNS services for itself or other hosts. The most version included in the two latest FreeBSD releases (4.7-RELEASE and 5.0-RELEASE) is 8.3.3-RELEASE. Similar to FreeBSD, there are two release branches for BIND: 8.x and 9.x; the 8.x release branch is the most prevelant version (as it is normally included in most UNIX releases, though some are still coming with 4.x!), but it is known for its history of nasty bugs. Although the 9.x release branch may look and feel like the 8.x, but a majority of its code has been rewritten in attempts to not acquire 8.x's (or even 4.x's) legacy of issues. In addition, 9.x includes some additional security features.
In this article, I will cover upgrading the base system's BIND from 8.x to version 9.2.2 (the steps have been tested on FreeBSD 4.6-RELEASE and newer, though it ought to work on 5.0-RELEASE) using Ports as well as building from source, as well as cover some of the changes and new features in BIND 9. I will not be covering how to install and configure BIND 9 in a chroot'd or jailed environment nor setting up BIND 9 to run as an un-priveleged user.
If you are wondering why you should upgrade the version of BIND that came with your FreeBSD install, mostly to a newer release branch, there are quite a few. Below is a list of some of the key reasons along with a brief description of the benefits of the 9.x release branch.
rndc
command.
Instead of having to SSH into a DNS server, and send a SIGHUP
to the BIND
process, you can just use rndc
from an authorized system and reload or refresh
specific zones or the entire server remotely.I will not be covering all of the new features of BIND 9.x in this article, but you can find out more about the new features and how to work with them in the BIND 9 Administrator Reference Manual or in DNS and BIND, 4th Edition. You can also refer to some of the other BIND 9 resources listed towards the end of this article.
Warning: As with any software installation or upgrade, please make sure that you have a recent backup of not only your BIND configuration and domain zone files, but the base system itself. There is always a chance that BIND 9.x could cause some problems with your system and may have to revert back to the previous version. If you still want to proceed but have some additional form of insurance, do not build/install with the options to replace the base system's BIND.
Before starting the build/install process using Ports, make sure that you have a fairly recent, if not up-to-date, Ports collection. If you need to update your local Ports collection and are not sure how to, please refer to the CVSup section of the FreeBSD Handbook for the necessary instructions.
Installing BIND 9 via Ports is the easiest way to get the software built and installed on your system.
By default, the dns/bind9 port (which has recently been updated for 9.2.2-REL instead of its release candidate,
9.2.2rc1) will install the package using the prefix of /usr/local
and sticks the configuration
directory under /usr/local/etc/namedb
, which does not replace the existing BIND
under /usr
. To do a basic build and install of BIND 9 without replacing the base
system's BIND, run the following as root:
# cd /usr/ports/dns/bind9 # make all install
Once the build/install process has finished and you want to have it use your existing BIND configuration
file, you will need to copy the contents of your /etc/namedb
(or the directory where your BIND
configuration files are located) into /usr/local/etc/namedb
. To start up the newly installed
(if you still have the original BIND running, kill that process first) BIND 9, run /usr/local/sbin/named
and keep a look out in your syslog for errors that make appear. If you are running a FreeBSD version before
4.3-RELEASE, you will most likely see the following error in your syslog; if so, you can safely ignore it.
fcntl(8, F_SETFL, 4): Inappropriate ioctl for device
If you get any other errors complaining about domain zone file or configuration errors, you will want to
jump down further in this article to see if the problems are known common problems and how to fix them.
To have the newly installed BIND be started automatically during the startup process, add the following
line into /etc/rc.conf
:
named_program="/usr/local/sbin/named"
To build/install the port and have it replace the base system's install, run the following commands as root:
# cd /usr/ports/dns/bind9 # make PORT_REPLACES_BASE_BIND9=yes all install
This will build and install BIND 9 so that it replaces the existing BIND binaries, as well as use the
default BIND configuration directory of /etc/namedb
. To start up the new BIND (making sure that
you stop the current BIND process first), just run the following as root:
# /usr/sbin/named
Make sure that you take a look at your syslog file to make sure that no warnings or fatal errors occurred. If any domain zone file or BIND configuration file errors occur, jump down further in this article to see if the problems are one of the more common ones.
If you are on the brave side or always liked to build/install software packages on your own, installing BIND 9 using ISC's tarball should be right down your alley. You can download the source tarball for BIND 9.2.2 from ISC's FTP server at ftp://ftp.isc.org/isc/bind9/9.2.2/bind-9.2.2.tar.gz. You can verify the tarball using ISC's PGP signature for the tarball or using the MD5 checksum for the tarball generated by the FreeBSD dns/bind9 port maintainer.
Once you have downloaded the tarball, uncompress and expand the tarball by running:
% tar zxf bind-9.2.2.tar.gz ; cd bind-9.2.2/
After expanding the tarball and going into the expanded source directory, you will need to run the
configure
script along with several flags depending on how you want to build/install BIND 9
or which compile options you would like to have. The following are the bare minimum configure
flags that you should provide if you want to install BIND 9 without replacing the base system's BIND:
% ./configure --prefix=/usr/local --localstatedir=/var --disable-threads \ --with-openssl=/usr
That will tell the configure
script to setup the build to install the binaries under
/usr/local
and will have the default configuration directory be /usr/local/etc
. If
you want to change the default configuration directory to be something else, add
--sysconfdir=/some/path
to the command above.
The bare minimum configure
flags required to install BIND 9 over the base system BIND are:
% ./configure --prefix=/usr --sysconfdir=/etc/namedb --mandir=/usr/share/man \ --localstatedir=/var --disable-threads --with-openssl=/usr
If you want to mimic the Ports build, add the following flags to either of the commands above:
--disable-linux-caps --with-randomdev=/dev/random
In theory, the configure
script should automatically detect and set those options, but it
may not always be the case. If you want to be on the safe side, you will want to include those flags.
I've built BIND 9 myself without those flags and haven't run into any problems under FreeBSD 4.7-PRERELEASE
or newer (but not with 5.0, either -CURRENT or -RELEASE). If you are feeling very
brave and daring (mostly when running any FreeBSD version prior to 5.0-RELEASE), you can enable multi-threading
support by adding --enable-threads
to either of the commands above.
After running the configure
command with the flags that you need, you are now ready to build and
install the files. To do so, run the following as root:
# make && make install
Once the build and install process has finished, you are now ready to start it up and see if the install
works or not. As root, run /usr/local/sbin/named
or /sbin/named
(depending on where you
installed BIND 9, also make sure to stop any running BIND processes first) and keep in eye out on your syslog
file to see if any errors or warnings appear.
After you've got BIND 9 installed and, hopefully, able to start up, now its time to take a look at your
BIND configuration to see if there are any items in your BIND configuration and zone files that BIND 9
may choke on, as well as two of the new features in BIND 9: views and rndc
.
In most cases, BIND 9 should be able to use an existing BIND 8.x configuration and domain zone files without too much or any tweaking. Along with the rewrite of the BIND code for BIND 9, BIND 9 also has a more strict configuration and domain zone file parser under its hood; it also means that instead of returning a warning, most configuration errors will cause BIND 9 to abort its startup process or ignore the domain zone completely. One of the most common mistakes that will trip up BIND 9 is how BIND 8 and BIND 9 deals with the SOA record at the beginning of every domain zone file. With BIND 8, the following SOA record would normally be treated as okay and a warning normally isn't issued, but BIND 9 will complain:
foobar.org. IN SOA plan9.foobar.org. outerspace.foobar.org. ( 1 10800 3600 604800 3600 )
The proper syntax should have the opening parenthesis on the same line as the "IN SOA
"
statement, rather than on the second line. In order for BIND 9 to load up the zone without any errors,
change the SOA record to be:
foobar.org. IN SOA plan9.foobar.org. outerspace.foobar.org. ( 1 10800 3600 604800 3600 )
It is also a good practice to include the zone's TTL before the SOA record by adding the following line at the very beginning of the zone file.
$TTL 3600
You can substitute 3600
with any value, though a value of 3600 (seconds, or the
same as one hour) should be fine unless if you want to keep its TTL low or high for a reason.
Below is a brief list of BIND configuration options that have been removed or its default value changed within the "options" section of the BIND configuration file. The BIND 9 Administrator Reference Manual provides a more in-depth description, default values and which options are no longer used or are ignored in BIND 9.
Configuration Option | Default Value | |
BIND 8 | BIND 9 | |
auth-nxdomain | yes | no |
rfc2308-type1 | no | Not Supported |
fetch-glue | - | Obsoleted |
named-xfer | - | Obsoleted |
deallocate-on-exit | - | Obsoleted |
host-statistics | - | Obsoleted |
The most important change between BIND 8 and 9 as noted in the table above is the default value for the "auth-nxdomain" option. This option is a fairly important option if the DNS server acts as a DNS proxy or caching server, and if the server should claim that its negative answer (i.e.: host or domain doesn't exist) is authoritative, even if that isn't the case.
As mentioned earlier in this article, BIND 9 brings along a new feature that may help consolidate DNS servers but also provide a form of who gets which answer based on where the request came from. In order for views to be setup in BIND 9, you will need to setup access control lists (or ACLs) and plan out how you want to setup your views.
Setting up ACLs in your BIND configuration file is fairly simple, though you will need to be fairly familiar with using slash notation for defining subnets. A very nice cheat sheet is available online which gives you a list of subnet masks and its corresponding slash notation (not all possible combinations are provided but it should provide you with enough to get you started). To define an ACL in BIND, you would add the following declaration to your BIND configuration file:
acl "acl-name" { a.b.c.d/slash; [...]; };
Where acl-name
is what you want to call the ACL set (the name string supports
alphanumeric characters and limited symbols such as a hyphen), a.b.c.d/slash
is
a subnet in slash notation that you want to associate to the ACL. For example, if you wanted to list
the entire 192.168.0.0 network in the ACL, you can either use 192.168.0.0/16
or
192.168/16
. Make sure that you trail the IP address or subnet address with a semi-colon.
Below is an example of an ACL that limits access to specific groups of addresses within an internal network:
acl "netadmins" { 10.1.2/24; 10.1.3/24; 10.1.4.5; };
Once you have defined your ACLs, now it is time to define the different views in your configuration file. A basic example configuration file with two views defined (one for the internal network and one for everyone else) would look something like:
acl "corpnet" { 10.1/16; }; view "internal" { match-clients { "corpnet"; }; zone "foobar.org" { type master; file "internal/map.foobar.org"; }; }; view "external" { match-clients { any; }; zone "foobar.org" { type master; file "external/map.foobar.org"; }; };
One thing that you might notice are the two different "match-clients" statements for the two views. Only requests that have a source address that matches the "corpnet" ACL would be served by the "internal" view, all other requests (matched by the "any" keyword) would be served by the "external" view. When building your views, keep in mind that BIND handles views in the order that they are defined in the configuration file. That means if the "external" view was defined first, it would catch all requests, leaving the "internal" view unused. The last view should always be treated as a catch-all for any requests that do not match the other views above it. You can also define multiple ACLs for "match-clients" if you wanted to make the ACL declarations any more granular.
The most important requirement when setting up views is that if you define a zone in one view, you must define the zone in all views, even if the zone data for multiple views are the same. That means that if you want to define an internal-only zone (for example: internal.foobar.org) and want to restrict query access to only the "corpnet" ACL, you would need to use the "allow-query" structure in the "external" view and list the "corpnet" ACL within it, as in the example below:
acl "corpnet" { 10.1/16; }; view "internal" { match-clients { "corpnet"; }; zone "foobar.org" { type master; file "internal/map.foobar.org"; }; zone "internal.foobar.org" { type master; file "internal/map.internal.foobar.org"; }; }; view "external" { match-clients { any; }; zone "foobar.org" { type master; file "external/map.foobar.org"; }; zone "internal.foobar.org" { type master; file "internal/map.internal.foobar.org"; allow-query { "corpnet"; }; }; };
If you forget to include a zone in all views in your BIND configuration file, the following error will be listed in syslog the next time you restart BIND or reload the configuration file:
Mar 2 11:10:17 foo named[135]: /etc/dns/named.conf:34: when using 'view' statements, all zones must be in views
If you are looking at using views on your DNS server and you host a lot of domains, this can easily
bloat up and make your BIND configuration file more chaotic, though you can use the include
statement and declare your different views as separate files. Using the example above, if we move each
"view" section into its own files, say views.internal
and views.external
,
you can shrink down the main configuration file to be:
acl "corpnet" { 10.1/16; }; // include internal view include "views.internal"; // include external/catch-all view include "views.external";
You may also want to plan your directory structure to accomodate your different views, one way is to create directories under the BIND configuration directory named for the different views and place the appropriate zone files into the corresponding directories. You can have multiple views point to the same zone file.
In BIND 9, you can use rndc
to remotely control a BIND 9 DNS server and run some basic
operations like reloading the server's configuration or clearing out the server's cache. Instead
of using a UNIX account to authenticate the user, rndc
uses a shared key authentication
system in which both the server and the users would use to gain access. Prior to BIND 9.2, you
had to manually generate the key and hack out the configuration files yourself. With the release of
BIND 9.2, getting rndc
configured and setup in BIND got much easier with the introduction
of the rndc-confgen
utility, which is included in your BIND 9.2.2 install. By default,
running the utility without any options will set the key size to 128-bits, allow only the local
system to control the DNS server, and display the configuration file contents back out to
the standard output; below is an example of the output:
# Start of rndc.conf key "rndc-key" { algorithm hmac-md5; secret "nm/mg36TVXZ7/fQSr9tD4g=="; }; options { default-key "rndc-key"; default-server 127.0.0.1; default-port 953; }; # End of rndc.conf # Use with the following in named.conf, adjusting the allow list as needed: # key "rndc-key" { # algorithm hmac-md5; # secret "nm/mg36TVXZ7/fQSr9tD4g=="; # }; # # controls { # inet 127.0.0.1 port 953 # allow { 127.0.0.1; } keys { "rndc-key"; }; # }; # End of named.conf
You will not want to use the example above for your DNS server, instead you will want to run
the utility yourself to generate a different secret as well as change the key's name to be
something less generic. Below are the more useful rndc-confgen
options that you will
want to look at and/or use.
rndc
configuration file using the
default key size and key file (the default keyfile is called rndc.key
and is
placed in the BIND 9 configuration directory). It is recommended that you change the key
file name and location by using the -c
option described below.rndc
configuration file; it
defaults to rndc.key
and places it under the BIND 9 configuration directory. It
is recommended that you set this option to be /path/to/dns/config/rndc.conf
so
that you don't have to manually rename or move the file later.rndc-confgen
to be
something different than the default name of "rndc-key". It is highly
recommended that you do change the key name, mostly on a DNS server that is on a network
that you may not have full knowledge or control over the traffic flowing through it,
mostly when you want to open up rndc
use to other machines on that network.
You can view the other rndc-confgen
options in the rndc-confgen(8) man page.
To generate a usable rndc.conf
file under the base system's BIND configuration directory,
/etc/namedb
, with the key name of "dnsadmin", and with a key size of 256 bits, run
the following command as root:
# rndc-confgen -a -c /etc/namedb/rndc.conf -k dnsadmin -b 256
Although rndc-confgen
will create the rndc
configuration file, it will
not touch your existing BIND configuration file. In order to tell BIND 9 to accept
control requests via rndc
, you will need to add the following lines to your
named.conf
file.
key "keyname" { algorithm hmac-md5; secret "secret-string"; }; controls { inet * allow { localhost; } keys { "keyname"; }; };
Replacing keyname
with the key name that you decided on using and
secret-string
with the secret string in the rndc.conf
file that was
generated. The "*
" within the "controls" section tells BIND that control
mechanism to listen to any addresses used by BIND. To allow multiple hosts to control BIND, using the
key keyname
, just add additional addresses with a trailing semi-colon within the
"allow" curly-brackets. You will also want to make sure that you allow port 953/tcp from the
remote machines to reach the DNS server. You can the port used by adding "default-port
portnum;
" to the "options" section of rndc.conf
and add
"port portnum
" after "inet *
" in your
named.conf
file.
On the machines that would use rndc
to control the DNS server, you will need to install BIND 9
on those machines and copy over the rndc.conf
generated on the server. If there is a firewall
in front of the remote machine, make sure that the firewall is set to allow the rndc
defined
TCP port through, or else the connection will fail. Below is a brief list of the most commonly used
rndc
control commands:
SIGHUP
signal to the named
process.named_dump.db
and is placed in your BIND configuration directory.named
processes.named.stats
, which is placed in your BIND configuration
directory.
Pairing up rndc
with one of its commands above without any other options will run the command
using the default server (typically localhost), ports and keys defined in rndc.conf
. To use
rndc
to connect to a different server, run:
rndc -s server
Replacing server
with the server's hostname or IP adress. To use a different port, use
the "-p port
" option, and to use a different key, use the "-k
keyname
" option. For more information on the different rndc
control commands
and run-time options, take a look at the rndc(8) man page.
As you can see, BIND 9 brings on many new and useful features to the BIND DNS software package, both on the server and administrative sides. There are many other features, nuances and tricks that aren't covered in this article, though you can find more information in both online and offline form listed at the end of this article.
I hope that you found this article to be informative and gives you the urge to move up to BIND 9. Spread the word around and help wave good-bye to BIND 8!
Looking for more information on BIND 9 or trying to figure out how something isn't working even after giving the server the mallet treatment? Below are some resources that pertain to BIND and/or BIND 9.
Article copyright © 2003–2010 Linh Pham. All rights reserved. Re-production of portions of this work, or its entirety, requires permission of the copyright holder.