Setting Up A Safe Nameserver On Red Hat Linux 6.x
A Twelve-Step Program
Jefferson Ogata <Jefferson.Ogata@noaa.gov>
These instructions will help you set up a chrooted nameserver running
as a non-root user under Red Hat Linux 6.x. This configuration is quite
safe even if a new remote vulnerability is discovered in BIND, because
the named process is running in a minimal environment with no access to
external programs, and without superuser privileges that could be used
to escape. Successful compromise via a nameserver configured this way
is extremely difficult if not altogether impossible.
See the ISC site for
documentation
on named's configuration file named.conf, and the special directives
for your zone files, and other
general information about
BIND.
Preliminary Steps
Please make sure that you have a clean machine in the first
place. Start from a fresh install of Red Hat done with the machine
disconnected from the network. Apply all current Red Hat patches
to the system before you connect it to the Internet. It is
pointless to set up a secure nameserver on a system that can be
compromised by other means.
Once all patches are applied, turn off all unnecessary services, and
eliminate all unencrypted means of remote shell access to the machine.
Disable inetd , sendmail , and all other network
services. Disable the window system.
Install sshd if you need remote access to the machine.
Setting up xntpd is also a good idea. Be aware that
xntpd will not start up at boot time if the machine time is
an hour or more in error. You may want to read up on the
setclock command for suggested remedies. An alternative to
running xntpd as a daemon is to execute ntpdate periodically
from a cron job.
I also recommend that you install autorpm and
perl-libnet , which you can get
here. You
will probably want to tweak the
/etc/autorpm.d/pools/redhat-updates file.
When you are done, reboot the machine. After reboot, the results of
running
should look more or less like this (TCP port 22 is sshd ):
If you have set up xntpd you should also see UDP port 123
active on each interface.
Now you may connect the machine to the Internet.
Setting Up The Nameserver
Please note: these instructions are for an initial setup. If you have already
performed these steps and are upgrading BIND from a Red Hat RPM, please see
the upgrade instructions below.
Please make sure you understand each step as we go. I will not
be held responsible for errors in this document. If you don't understand
a step, please don't blame me when something unexpected happens.
You should perform all the following steps as the root user. Make sure
your umask is set to a suitable value, such as 022.
In all steps, we are making an effort to preserve modification times on
copied files, using the cp -p command or using
tar . This is important because it will help you tell which
files in the chroot hierarchy need to be replaced after applying future
patches to system libraries or the BIND subsystem.
- Stop
named if it is already running. (If you followed
the preliminary steps listed above, it isn't.)
- Make sure there is a named user on your system. If there is not,
create one with suitable non-zero uid and gid, an invalid shell, and
an unusable password.
- Set up a chroot hierarchy for
named . When we are done,
named will run with /var/roots/named as its root
directory. This will make all files outside of /var/roots/named
inaccessible to the named process. If compromised,
named will be extremely limited in what actions it can
perform on an attacker's behalf.
mkdir /var/roots
mkdir /var/roots/named
mkdir /var/roots/named/{dev,etc,lib,usr,var}
mkdir /var/roots/named/usr/sbin
mkdir /var/roots/named/var/run
- The following steps are necessary if you are acting as a slave
server. If you are acting only as a master, you may skip this section.
On the other hand, there's no harm in performing these steps, and you
will then be able to act as a slave later on without further
modifications.
- Copy the
named-xfer program into the hierarchy.
named invokes this program to transfer slave zones from other
nameservers.
- Copy necessary libraries for
named-xfer . We use
cp 's -d flag to preserve the fact that some of
these objects are symbolic links.
You may need to adjust the above command for the versions of
libc and ld that are current for Red Hat Linux.
The ldd command is useful for determining what versions of
which libraries are used to link and run a given binary.
- Make a directory for slave zone files -- it must belong to the
named user so that the
named and named-xfer
processes can write to it.
- Copy
/etc/localtime . Log messages will appear in UTC
without it.
- Copy configuration and database files. Important: do not
make soft links to the chrooted configuration file and zone file directory.
linuxconf likes to "clean up" your zone files and it makes a
royal mess out of them, actually making incorrect modifications.
You might want to drop a README in /var/named and
some comments in /etc/named.conf pointing your colleagues to
the appropriate locations under /var/roots/named .
- Now we have to fix up
named and ndc in
/usr/sbin . We will replace the original versions with shell
scripts to set a few extra options during invocation. ndc , by
the way, is the name daemon control program, which lets you do a lot
of things to the running nameserver, such as reloading a specific zone,
checking status, restarting the daemon, etc.
- Move original binaries to a new spot.
- Create a stub for
ndc so it can find the control channel
in the chroot hierarchy. Normally, ndc would look in /var/run/ndc ,
but this path will be inaccessible to named when it creates its
control channel. Instead, the control channel will end up in
/var/roots/named/var/run/ndc .
- Create a stub for
named that will chroot to the new
hierarchy and run as the named user.
- Set up logging:
named wants to log to
/dev/log , but there is no /dev/log in the chroot
hierarchy. We address this problem by telling syslogd to bind
to an additional socket in an appropriate place in the chroot hierarchy,
using the -a flag. This requires tweaking the syslogd
startup script.
- First backup the old script:
- To be consistent with the rest of Red Hat's configuration
structure, create
/etc/sysconfig/syslogd with the following:
- And make the following changes to /etc/rc.d/init.d/syslog:
- After:
add the following:
- Change the line:
to:
- Restart
syslogd . After restart you should find a
UNIX-domain socket at /var/roots/named/dev/log .
- Customize
/var/roots/named/etc/named.conf now.
Any place you see an IP address below, make a suitable change. Good
things to have in your named.conf :
options {
directory "/var/named";
// Enumerate hosts to whom we allow zone transfers.
allow-transfer {
192.168.0.1; // Add all slave server addresses here.
192.168.0.2;
};
// Make up something here. It is preferable not to reveal the
// version of BIND you are using.
version "over 8 billion served";
// You don't need to write a pid file. ndc talks to the UNIX
// socket. This will cause an error message at startup, but that
// is okay; it is harmless.
pid-file "/no/such/path/named.pid";
// Set the source address you will use for outgoing queries.
// If you want to specify the IP address as well, replace the
// asterisk in the third field.
query-source address * port 53;
// Set the source address we use for outgoing zone transfer
// requests. If you are acting as a slave and have multiple
// network interfaces, it is important to do this so that the
// master servers can be configured to allow transfers from a
// consistent address. If you don't do this, you may end up
// expiring a valid zone.
transfer-source 192.168.0.53;
};
// You probably don't need to log statistics. They make a lot of noise.
logging {
category statistics {
null;
};
};
- You can now start
named .
You should see messages similar to the following appear in
/var/log/messages :
You should also be able to retrieve your dummy version string with the
following command:
- Make sure
named is enabled in the configuration for runlevels 2
through 5:
And you're done. You might want to reboot at this point to make sure
everything starts up okay.
Upgrading The Nameserver
Periodically Red Hat issues an RPM containing a new version of BIND. This
RPM may replace the named , ndc ,
named-xfer , and various other binaries, as well as various
library files. Since some of these files have been copied to the chroot
hierarchy, while certain other files in /usr/sbin have been
replaced with stub scripts, you must perform additional steps to make
everything work properly after a BIND upgrade. This is also the case if
you upgrade the C library (glibc package) or the syslog daemon
(sysklogd package).
- Stop
named .
- Install the new RPMs using the "freshen" option (
-F ):
- If you set up your nameserver originally as a slave server, make sure
your
named-xfer binary and any required libraries in the chroot
hierarchy are up to date. If your nameserver does not already have a copy of
named-xfer in the chroot hierarchy, skip this step.
- Re-copy the
named-xfer program into the hierarchy.
- Re-copy necessary libraries for
named-xfer .
As in the initial setup, you may need to adjust the above command for
the versions of libc and ld that are current for
Red Hat Linux.
- Now we have to make sure our modified versions of
named
and ndc in /usr/sbin are correct. We had replaced
the original versions with shell scripts as part of the initial setup. The
new RPM may have overwritten one or both of our scripts with new
binaries. We'll start by examining ndc .
If file describes ndc as Bourne shell
script text , then the shell script is intact, and you should skip the
remainder of this step. If, however, ndc is a dynamically linked
executable, then the RPM has replaced our shell script with a new binary, and
we need to perform the following steps:
- Move the new
ndc binary to our bind-orig
directory. In the process, we will overwrite the old version of
ndc which we had moved there during the initial setup.
- Re-create the stub for
ndc so it can find the control
channel in the chroot hierarchy.
- Examine the
named program in /usr/sbin .
This step is independent of the previous step. Regardless of whether we had
to re-create the ndc stub, we must still examine
named , as Red Hat may distribute an RPM that updates
named but not ndc , or vice versa.
If file describes named as Bourne shell
script text , then the shell script is intact, and you should skip the
remainder of this step. If, however, named is a dynamically
linked executable, then the RPM has replaced our shell script with a new
binary, and we need to perform the following steps:
- Move the new
named binary to our bind-orig
directory. In the process, we will overwrite the old version of
named which we had moved there during the initial setup.
- Re-create the stub for
named that will chroot to the
chroot hierarchy and run as the named user.
- Make sure
syslogd has a logging socket in the chroot
hierarchy. Updates to the sysklogd package may overwrite the
init.d startup script, which we modified to append options to
the syslogd command line. Check that our modifications are
intact using the following command:
If grep reports the line
then our changes are still intact, and you should skip the remainder of this
step. If, however, grep reports no occurrence of
SYSLOGD_OPTS , then we must redo our changes to the
/etc/rc.d/init.d/syslog script as follows:
- First backup the old script:
- Make the following changes to /etc/rc.d/init.d/syslog:
- After:
add the following:
- Change the line:
to:
- Restart
syslogd . After restart you should find a
UNIX-domain socket at /var/roots/named/dev/log .
- You can now start
named .
You should see messages similar to the following appear in
/var/log/messages :
And you are finished upgrading the nameserver. At this point you should
enjoy a cold, refreshing beverage of your choice.
|