Nowadays, security software like AppArmor, which restrict program accesses to the operating system, are by default distributed and integrated on most GNU/Linux systems.
When correctly configured, their use make the configuration of a chroot jail, as described on this page, unnecessary. This solution will however still be of interest in case you do not wish to use a software such as AppArmor.
Package installation
If you don't use BIND yet, on Debian you will simply need to install the
package bind9
(which will lead to the automatic installation of required
packages such as bind9utils
).
Its configuration is outside the scope of this document, but note that after
installation, the package default configuration will run the named
daemon as
the user bind
, which is a member of the group bind
.
All commands given in this document are meant to be run as the system superuser
(usually root
). This usually means you should either prefix each command by
the command sudo
, or run them in a root shell created using, for example,
the command sudo -i
.
Setup of the chroot jail
Creation of the chroot jail directories
The choice of the directory where the chroot jail will be installed (and to
which the daemon accesses will be restricted) is free, but in this document,
we will choose the directory /var/lib/bind
which was created to this effect
by the Debian package.
We can recreate the files and directory structure required by BIND in this directory using the following commands :
We also need to create the two character devices files required by BIND:
Copy of the configuration files
Before moving files, it can be worth backing them up somewhere. I'm used to
keep these kinds of safety backups in the directory /var/local/backups
that
I create if it does not exist :
||
Note: if your BIND server manages dynamic DNS zones, it is advised to stop it
now (using the command service bind9 stop
), or you would risk losing zone
updates that would occur between the copy of the files below and the restart of
BIND in its new chroot jail. If the server does not manage dynamic zone, you
can keep it running while setting up the chroot jail and only restart it once
it is ready.
We now can copy configuration files to the chroot directory (we do a copy instead of a move to not prevent BIND from operating normally during our chroot setup; we will remove the old files at the end of the procedure):
Copy of the cache
This operation is mainly useful if the server is configured as a slave for at least one DNS zone, as this will avoid it to transfer the zone(s) from the master server again:
Modification of directory owner and permissions
The named daemon needs to be able to write in the cache directory (where it
writes zones for which it is a slave, in particular) and in the directory where
it writes its PID file (the file named.pid
):
We then further restrict the permissions of the main chroot directory, for security purpose and to follow best practices:
Modification of the syslog configuration
On GNU/Linux, BIND by default communicates with the syslog daemon using the
Unix socket file
/dev/log
. As, by definition, BIND will only be able to access files within
the chroot jail, we need to configure the syslog daemon so that it creates
another socket file inside the jail and read from it what BIND will write.
In our example, we will use the socket /var/lib/bind/dev/log
.
This configuration will depend on the syslog daemon you use. Using rsyslog
(used by default on Debian), we can modify the configuration of the daemon by
creating a file in /etc/rsyslog.d
, for example using the following command:
Then we simply need to restart rsyslog:
Note: if you use the syslog daemon sysklogd (which was in particular the
default syslog daemon on Debian Etch), edit /etc/default/syslogd
and modify
the variable definition SYSLOGD=""
into SYSLOGD="-a /var/lib/bind/dev/log"
,
for example using the following command:
Adaptation of the startup configuration
We then need to adapt the startup configuration for BIND so that the named
daemon is run using the -t
option that requests the use of a chroot jail in
the specified directory.
For this, we need to edit BIND startup configuration file /etc/default/bind9
,
to change the variable declaration OPTIONS="-u bind"
into OPTIONS="-u bind -t /var/lib/bind"
. This can be achieved using this command:
Caution: on Debian 8 (Jessie), a bug in the bind9
package prevents the
named daemon from taking into account the options provided by the file
/etc/default/bind9
if you use systemd (which is the default).
To work around this problem, we need to modify the systemd configuration of
BIND by editing the file /lib/systemd/system/bind9.service
. Replace the line
starting by ExecStart=
with these two lines:
EnvironmentFile=-/etc/default/bind9
ExecStart=/usr/sbin/named
This operation can be achieved directly using the following command, before reloading the systemd configuration:
Beware that changing this file means that each update of the bind9
package
will reinstall the original file, overwriting your modifications, and named
would then be restarted without using the chroot jail. To ask the package not
to overwrite this file, a file diversion can be put in place with this command:
After the bug is corrected, the file diversion can be removed using this command:
For more information on these last commands, see the tip « File diversions on Debian »
Restart of the BIND daemon
The configuration of the BIND chroot is now finished. You can restart the bind9 service, which will restart the named daemon using the chroot:
Directory cleanup (optional)
After having made sure that everything works correctly after the restart, we
can remove the original files from /etc/bind
(as BIND now uses files from the
chroot jail, /var/lib/bind/etc/bind
in our example) and the cache files from
/var/cache/bind
.
Caution: before removing, make extra sure the files from /etc/bind
were
all correctly copied to /var/lib/bind/etc/bind
!
If we want to make the chroot jail configuration transparent for the system
administrators, we can replace /etc/bind
by a link to
/var/lib/bind/etc/bind
:
Summary
Recap of the commands
Below is the recap of all commands given and described above, that need to be run to configure the chroot jail (we will suppose here that we use the rsyslog daemon).
Be cautious, as some configuration details certainly have changed in newer version of BIND on Debian since the writing of this documentation. I recommend to only execute these commands one by one to verify and correct any potential error as you go along.
# Stopping BIND
# Creation of the chroot jail under /var/lib/bind
# Backup of the BIND files (optional)
[ ||
# Copy of the files to the chroot jail
# Modification of file permissions and owners
# Configuration of rsyslog
# Adding the option -t to named to specify the chroot
# Before removing these files, make sure everything works fine
# in the chroot and/or that you backed them up somewhere!
# Optional operation to ease the access to BIND files for admins
An example of the directory structure of a pristine configuration
As a reference, below are the files and directories you would find in the
chroot jail (in our example, this is the content of the directory
/var/lib/bind
) after applying the chroot configuration on a pristine
installation of the bind9
package on Debian 8 (Jessie) (this list was
produced by the command tree /var/lib/bind
):
/var/lib/bind
├── bind9-default.md5sum
├── dev
│ ├── log
│ ├── null
│ └── random
├── etc
│ ├── bind
│ │ ├── bind.keys
│ │ ├── db.0
│ │ ├── db.127
│ │ ├── db.255
│ │ ├── db.empty
│ │ ├── db.local
│ │ ├── db.root
│ │ ├── named.conf
│ │ ├── named.conf.default-zones
│ │ ├── named.conf.local
│ │ ├── named.conf.options
│ │ ├── rndc.key
│ │ └── zones.rfc1918
│ └── localtime
└── var
├── cache
│ └── bind
│ ├── managed-keys.bind
│ └── managed-keys.bind.jnl
└── run
└── named