Bind-Chroot-Howto (Debian)

Bind-Chroot-Howto (Debian)

Version 1.3
Author: Falko Timme <falko [dot] timme [at] projektfarm [dot] de>
Last edited 08/16/2006

This document describes how to install the DNS server Bind on Debian so that it runs out of a chroot jail for security reasons.

This howto is meant as a practical guide; it does not cover the theoretical backgrounds. They are treated in a lot of other documents in the web.

This document comes without warranty of any kind!

 

Install Bind And Chroot It

apt-get install bind9

For security reasons we want to run BIND chrooted so we have to do the following steps:

/etc/init.d/bind9 stop


On Debian Sarge (3.1):

Edit the file /etc/default/bind9 so that the daemon will run as the unprivileged user 'bind', chrooted to /var/lib/named. Modify the line: OPTS="-u bind" so that it reads OPTS="-u bind -t /var/lib/named":

OPTIONS="-u bind -t /var/lib/named"

 

On Debian Woody (3.0):

Edit the startup script /etc/init.d/bind9 so that the daemon will run as the unprivileged user 'nobody', chrooted to /var/lib/named. Modify the line: OPTS="" so that it reads OPTS="-u nobody -t /var/lib/named":

#!/bin/sh

PATH=/sbin:/bin:/usr/sbin:/usr/bin

# for a chrooted server: "-u nobody -t /var/lib/named"
OPTS="-u nobody -t /var/lib/named"

test -x /usr/sbin/named || exit 0

case "$1" in
    start)
        echo -n "Starting domain name service: named"
        start-stop-daemon --start --quiet \
            --pidfile /var/run/named.pid --exec /usr/sbin/named -- $OPTS
        echo "."
    ;;

    stop)
        echo -n "Stopping domain name service: named"
        /usr/sbin/rndc stop
        echo "."
    ;;

    reload)
        /usr/sbin/rndc reload
    ;;

    restart|force-reload)
        $0 stop
        sleep 2
        $0 start
    ;;

    *)
        echo "Usage: /etc/init.d/bind {start|stop|reload|restart|force-reload}" >&2
        exit 1
    ;;
esac

exit 0

Create the necessary directories under /var/lib:

mkdir -p /var/lib/named/etc
mkdir /var/lib/named/dev
mkdir -p /var/lib/named/var/cache/bind
mkdir -p /var/lib/named/var/run/bind/run

Then move the config directory from /etc to /var/lib/named/etc:

mv /etc/bind /var/lib/named/etc

Create a symlink to the new config directory from the old location (to avoid problems when bind is upgraded in the future):

ln -s /var/lib/named/etc/bind /etc/bind

Make null and random devices, and fix permissions of the directories:

mknod /var/lib/named/dev/null c 1 3
mknod /var/lib/named/dev/random c 1 8
chmod 666 /var/lib/named/dev/null /var/lib/named/dev/random


On Debian Sarge (3.1):

chown -R bind:bind /var/lib/named/var/*
chown -R bind:bind /var/lib/named/etc/bind

On Debian Woody (3.0):

chown -R nobody:nogroup /var/lib/named/var/*
chown -R nobody:nogroup /var/lib/named/etc/bind


We need to modify the startup script /etc/init.d/sysklogd of sysklogd so that we can still get important messages logged to the system logs. Modify the line: SYSLOGD="" so that it reads: SYSLOGD="-a /var/lib/named/dev/log":

#! /bin/sh
# /etc/init.d/sysklogd: start the system log daemon.

PATH=/bin:/usr/bin:/sbin:/usr/sbin

pidfile=/var/run/syslogd.pid
binpath=/sbin/syslogd

test -x $binpath || exit 0

# Options for start/restart the daemons
#   For remote UDP logging use SYSLOGD="-r"
#
SYSLOGD="-a /var/lib/named/dev/log"

create_xconsole()
{
    if [ ! -e /dev/xconsole ]; then
        mknod -m 640 /dev/xconsole p
    else
        chmod 0640 /dev/xconsole
    fi
    chown root.adm /dev/xconsole
}

running()
{
    # No pidfile, probably no daemon present
    #
    if [ ! -f $pidfile ]
    then
        return 1
    fi

    pid=`cat $pidfile`

    # No pid, probably no daemon present
    #
    if [ -z "$pid" ]
    then
        return 1
    fi

    cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -1`

    # No syslogd?
    #
    if [ "$cmd" != "$binpath" ]
    then
        return 1
    fi

    return 0
}

case "$1" in
  start)
    echo -n "Starting system log daemon: syslogd"
    create_xconsole
    start-stop-daemon --start --quiet --exec $binpath -- $SYSLOGD
    echo "."
    ;;
  stop)
    echo -n "Stopping system log daemon: syslogd"
    start-stop-daemon --stop --quiet --exec $binpath --pidfile $pidfile
    echo "."
    ;;
  reload|force-reload)
    start-stop-daemon --stop --quiet --signal 1 --exec $binpath --pidfile $pidfile
    ;;
  restart)
    echo -n "Stopping system log daemon: syslogd"
    start-stop-daemon --stop --quiet --exec $binpath --pidfile $pidfile
    echo "."
    sleep 1
    echo -n "Starting system log daemon: syslogd"
    start-stop-daemon --start --quiet --exec $binpath -- $SYSLOGD
    echo "."
    ;;
  reload-or-restart)
    if running
    then
        start-stop-daemon --stop --quiet --signal 1 --exec $binpath --pidfile $pidfile
    else
        start-stop-daemon --start --quiet --exec $binpath -- $SYSLOGD
    fi
    ;;
  *)
    echo "Usage: /etc/init.d/sysklogd {start|stop|reload|restart|force-reload|reload-or-restart}"
    exit 1
esac

exit 0

Restart the logging daemon:

/etc/init.d/sysklogd restart

Start up BIND, and check /var/log/syslog for any errors:

/etc/init.d/bind9 start

Good luck!

Share this page:

17 Comment(s)

Add comment

Comments

From: Anonymous at: 2005-10-28 07:10:57

Firstly thanks for the howto. I had to recently get a name server

up and running and was happy to find your tutorial.

Just one thing! I followed your instructions to the letter but was

unsuccessful in getting the nameserver to start. I looked in the

log files and saw the following:

couldn't open pid file '/var/run/bind/run/named.pid': No such

file or directory.

I created a file /var/lib/named/var/run/bind/run started the server again and all was fine.

Thanks again.

t. ir

From: Anonymous at: 2005-10-28 09:02:10

Sorry, the above should read:

I created a directory /var/lib/named/var/run/bind/run...

t. ir

From: Anonymous at: 2005-12-13 14:35:43

This line:
mkdir /var/lib/named/var/run

Should read:

mkdir -p /var/lib/named/var/run/bind/run

From: Anonymous at: 2006-01-18 04:04:30

Thanks for posting about the /var/lib/named/var/run/bind/run fix. I had the same issue and the posts made short work of fixing it!

From: Anonymous at: 2006-01-29 19:50:49

One final required step that I discovered, is that you have to then run chown -R bind:bind /var/lib/named/var/run/bind/run

Dunno if that's supposed to be obvious, but I thought I'd mention it.

From: Anonymous at: 2006-05-17 21:31:20

good thing you mentioned it.

From: joe at: 2005-11-01 00:33:20

I followed through the tutorial yesterday and found that as well. I also noticed on my Debian box, I have a file /etc/defaults/bind9. Inside is another OPTIONS environment variable. You must comment this out or it will take precedence over the init.d script.

Great guide!

From: admin at: 2005-11-01 08:52:06

I've just checked that, it happens if you simply copy over the bind9 init script from the tutorial because it is from Debian Woody. If you simply change the line

OPTS=""

in the existing bind9 init script all works well.

From: Anonymous at: 2005-11-16 08:58:35

when i am stop the bind9 show error :

ns1:/home/dadang# /etc/init.d/bind9 stop

Stopping domain name service: namedrndc: connect failed: connection refused

From: Anonymous at: 2005-11-18 22:11:15

If you notice in the tutorial, it says - for Sarge - to modify the /etc/default/bind9 so bind runs as the unprivileged user 'bind'. Problem is, later on we chroot everything to the user 'nobody' I changed the opts= line in /etc/default/bind9 as per the instructions but used 'nobody' instead of 'bind' and it all worked fine - got rid of both the 'connect failed' AND the 'named.pid' error in syslog !. btw: Great howto - but I guess even the greatest stuff can have errors :)

From: admin at: 2005-11-19 11:30:26

Thanks for the hint. I've corrected the bug. :-)

From: at: 2007-11-21 21:53:16

When Bind is not chrooted, it uses all 4 CPU's:

starting BIND 9.3.4 -u bind

found 4 CPUs, using 4 worker threads

 

But when Bind is chrooted, it only detects 1 CPU:

starting BIND 9.3.4 -u bind -t /var/lib/named

found 1 CPU, using 1 worker thread 

 

When I then add "-n 4" to startup, it still uses 1 CPU, but with 4 threads:

starting BIND 9.3.4 -u bind -n 4 -t /var/lib/named

found 1 CPU, using 4 worker threads

 

Anyone also with this problem or a solution for this?

Thnx 

From: at: 2012-06-18 06:32:40

G'day Everyone,

The above instructions still work for Debian Wheezy, with 1 additional change. Bind98 need's a file from the SSL library. Simply create the relavent folder in the chroot, then copy the library.

mkdir -p /var/lib/named/usr/lib/i386-linux-gnu/openssl-1.0.0/engines
cp /usr/lib/i386-linux-gnu/openssl-1.0.0/engines/libgost.so /var/lib/named/usr/lib/i386-linux-gnu/openssl-1.0.0/engines

Hope this helps someone.

From: Anonymous at: 2012-12-18 08:21:37

i have not libgost.so file, what can i do?

From: at: 2013-05-26 13:40:36

Thanks, it helped me :)  Re the comment about not having libgost, I had that problem because my system is not i386 (it's amd64).  The simplest solution is to use updatedb (if needed) and locate to look for libgost.  Then make a directory that matches where you found libgost but with /var/lib/named in front, then copy libgost.so to the new directory.

From: at: 2014-02-25 03:48:40

After the chroot, If you get this error when you check bind9 status:


# /etc/init.d/bind9 status
bind9 is not running failed!

 you need to edit the PIDFILE in /etc/init.d/bind9 script when bind is running :

...
PIDFILE=/var/run/bind/run/named.pid
...

to

PIDFILE=/var/chroot/var/run/bind/run/named.pid 
( in my case the named.pid is located in this way )

Save bind9 script, and check bind9 status again

 

 

From: Paul Theodoropoulos at: 2014-08-07 00:14:55

While it's very useful to have the extended info in the original howto above - once you've mastered it, and want to replicate it again elsewhere, here's a streamlined 'howto' - you can just paste this on the command line (after sudo -i to root!). Works for both deb squeeze and wheezy.

apt-get install bind9
sed -i "s/-u bind/-u bind -t \/var\/lib\/named/g" /etc/default/bind9
mkdir -p /var/lib/named/{etc,dev,var/{cache/bind,run/bind/run}}
mv /etc/bind /var/lib/named/etc
ln -s /var/lib/named/etc/bind /etc/bind
ln -s /var/lib/named/etc/bind /etc/bind9
ln -s /var/lib/named/etc/bind /named
mknod /var/lib/named/dev/null c 1 3
mknod /var/lib/named/dev/random c 1 8
chmod 666 /var/lib/named/dev/null /var/lib/named/dev/random
chown -R bind:bind /var/lib/named/var/*
chown -R bind:bind /var/lib/named/etc/bind
service bind restart

In Squeeze and Wheezy, the bind output goes to /var/log/daemon.log, so the logging mods in the original aren't necessary.

Cheers!