As mentioned in the introduction, it's not a good idea to run BIND as root. So,
before we begin, let's create a separate user for BIND. Note that you should
never use an existing generic user like
nobody for this purpose.
However, some distributions, such as SuSE and Linux Mandrake have started
providing a specific user (generally called
named); you can simply adapt
this user for our purposes, if you like.
This requires adding a line something like the following to
And one like this to
This creates a user and group called
namedfor BIND. Make sure that the UID and GID (both 200 in this example) are unique on your system. The shell is set to
/bin/falsebecause this user will never need to log in.
Now, we must set up the directory structure that we will use for the chroot jail
in which BIND will live. This can be anywhere on your filesystem; the truly
paranoid may even want to put it on a separate volume. I shall assume that you
/chroot/named. Let's start by creating the following directory
/chroot +-- named +-- dev +-- etc | +-- namedb | +-- slave +-- var +-- run
Assuming that you have already done a conventional installation of BIND and are
using it, you will already have an existing
named.conf and zone files.
These files must now be moved (or copied, to be safe) into the chroot jail, so
that BIND can get at them.
named.conf goes in
and the zone files can go in
/chroot/named/etc/namedb. For example:
# cp -p /etc/named.conf /chroot/named/etc/ # cp -a /var/named/* /chroot/named/etc/namedb/
BIND would normally need to write to the
namedb directory, but in the
interests of tightening security, we will not allow it to do this. If your
nameserver serves as a slave for any zones, it will need to update these zone
files, which means we'll have to store them in a separate directory, to which
BIND does have write access.
# chown -R named:named /chroot/named/etc/namedb/slave
Keep in mind that'll you have to move any slave zones you have into this
directory, and update your
BIND will also need to write to the
/var/run directory, to put its
pidfile and statistical information there, so let's allow it to do so:
# chown named:named /chroot/named/var/run
Once BIND is running in the chroot jail, it will not be able to access files outside the jail at all. However, it needs to access a few key files, although not nearly as many as BIND 8 did.
One file that BIND will need inside its jail is good ol'
Note that the exact command necessary to create this device node may vary from
system to system; check your
/dev/MAKEDEV script to be sure. Some
systems may also require
/dev/zero, which can created similarly. For
most Linux systems, we can use the following command:
# mknod /chroot/named/dev/null c 1 3
You also need another file in the
/etc directory inside the jail. You
/etc/localtime (this is sometimes known as
/usr/lib/zoneinfo/localtime on some systems) in there so that BIND logs
things with the right time on them. The following command will take care
# cp /etc/localtime /chroot/named/etc/
Unlike a conventional jailbird, BIND can't just scribble its log entries on the
walls :-). Normally, BIND logs through
syslogd, the system logging daemon.
However, this type of logging is performed by sending the log entries to the
/dev/log. Since this is outside the jail, BIND can't use
it any more. Fortuantely, there are a couple options to work around this.
The ideal solution to this dilemma requires a reasonably recent version of
syslogd which supports the
-a switch introduced by OpenBSD.
Check the manpage for your
syslogd(8) to see if you have such a
If you do, all you have to do is add the switch ``
/chroot/named/dev/log'' to the command line when you launch
On systems which use a full SysV-init (which includes most Linux distributions),
this is typically done in the file
/etc/rc.d/init.d/syslog. For example,
on my Red Hat Linux system, I changed the line
daemon syslogd -m 0
daemon syslogd -m 0 -a /chroot/named/dev/log
On Caldera OpenLinux systems, they use a daemon launcher called
which reads configuration from
simply need to modify the options line to look like this:
OPTIONS_SYSLOGD="-m 0 -a /chroot/named/dev/log"
Similarly, on SuSE systems, I'm told that the best place to add this switch
is in the
/etc/rc.config file. Changing the line
should do the trick.
Once you've figured out how to make this change for your system, simply
syslogd, either by killing it and launching it again (with
the extra parameters), or by using the SysV-init script to do it for you:
# /etc/rc.d/init.d/syslog stop # /etc/rc.d/init.d/syslog start
Once it's been restarted, you should see a ``file'' in
log, that looks something like this:
srw-rw-rw- 1 root root 0 Mar 13 20:58 log
If you have an older
syslogd, then you'll have to find another way to do
your logging. There are a couple programs out there, such as
which are designed to help by acting as a ``proxy'' and accepting log entries
from the chrooted BIND and passing them out to the regular
Alteratively, you can simply configure BIND to log to files instead of going through syslog. See the BIND documentation for more details if you choose to go this route.
First of all, feel free to restrict access to the whole
directory to the
root user. Of course, not everybody may want to do
this, especially if you have other software installed in that tree that
doesn't appreciate it.
# chown root /chroot # chmod 700 /chroot
You can also safely restrict access to
/chroot/named to the
# chown named:named /chroot/named # chmod 700 /chroot/named
For even more tightening, on Linux systems we can make a few of the files and
directories immutable, using the
chattr tool on ext2 filesystems.
# cd /chroot/named # chattr +i etc etc/localtime var
It would be nice to do this for the
dev directory too, but unfortunately
that would prevent
syslogd from creating its
You may also choose to set the immutable bit on other files in the jail as
well, such as your primary zone files, if they aren't expected to change.