Next Previous Contents

## 2. Preparing the Jail

## 2.1 Creating a User

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 `/etc/passwd`:

> `

>     named:x:200:200:Nameserver:/chroot/named:/bin/false

> `

And one like this to `/etc/group`:

> `

>     named:x:200:

> `

This creates a user and group called `named` for BIND. Make sure that the UID and GID (both 200 in this example) are unique on your system. The shell is set to `/bin/false` because this user will never need to log in.

## 2.2 Directory Structure

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 will use `/chroot/named`. Let's start by creating the following directory structure:

> `

>     /chroot
>       +-- named
>            +-- dev
>            +-- etc
>            |    +-- namedb
>            |         +-- slave
>            +-- var
>                 +-- run

> `

If you use GNU `mkdir` (such as on a Linux system), you can create this directory structure like this:

> `

>     # mkdir -p /chroot/named
>     # cd /chroot/named
>     # mkdir -p dev etc/namedb/slave var/run

> `

## 2.3 Placing the BIND Data

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 `/chroot/named/etc`, 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 `named.conf` accordingly.

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

> `

## 2.4 System Support Files

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' `/dev/null`. 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. It's reported that the BIND 9.2.0 release candidates now require `/dev/random` as well. For most Linux systems, we can use the following commands:

> `

>     # mknod /chroot/named/dev/null c 1 3
>     # mknod /chroot/named/dev/random c 1 8
>     # chmod 666 /chroot/named/dev/{null,random}

> `

For FreeBSD 4.3, this is:

> `

>     # mknod /chroot/named/dev/null c 2 2
>     # mknod /chroot/named/dev/random c 2 3
>     # chmod 666 /chroot/named/dev/{null,random}

> `

You also need another file in the `/etc` directory inside the jail. You must copy `/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 of this:

> `

>     # cp /etc/localtime /chroot/named/etc/

> `

## 2.5 Logging

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 special socket `/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

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 version.

If you do, all you have to do is add the switch ```-a /chroot/named/dev/log`'' to the command line when you launch `syslogd`. 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

> `

to

> `

>     daemon syslogd -m 0 -a /chroot/named/dev/log

> `

Interestingly, as of Red Hat 7.2, Red Hat has apparently made this process even easier. There is now a file called `/etc/sysconfig/syslog` in which extra parameters for syslogd can be defined.

On Caldera OpenLinux systems, they use a daemon launcher called `ssd`, which reads configuration from `/etc/sysconfig/daemons/syslog`. You 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

> `

>     SYSLOGD_PARAMS=""

> `

to read

> `

>     SYSLOGD_PARAMS="-a /chroot/named/dev/log"

> `

should do the trick.

And, last but not least, for FreeBSD 4.3 you can apparently just edit the `rc.conf` file and put in the following:

> `

>     syslogd_flags="-s -l /chroot/named/dev/log"

> `

The `-s` is for security reasons, and is part of the default settings. The `-l` is a local path on which to put another logging node.

Once you've figured out how to make this change for your system, simply restart `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 `/chroot/named/dev` called `log`, that looks something like this:

    srw-rw-rw-   1 root     root            0 Mar 13 20:58 log

### The Other Solutions

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 `holelogd`, 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 `/dev/log` socket.

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.

## 2.6 Tightening Permissions

First of all, feel free to restrict access to the whole `/chroot` 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 `named` user.

> `

>     # 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

> `

Equivalently, on FreeBSD 4.3, you want to look into `chflags` if you wish to make things immutable. As an example, the following should change everything in the `/chroot/named/etc` directory to immutable:

> `

>     # chflags schg /chroot/named/etc/*(*).

> `

It would be nice to do this for the `dev` directory too, but unfortunately that would prevent `syslogd` from creating its `dev/log` socket. 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.

Next Previous Contents