Bind-Chroot-Howto (Debian)

Want to support HowtoForge? Become a subscriber!
 
Submitted by falko (Contact Author) (Forums) on Thu, 2005-02-03 17:21. :: BIND | Debian | DNS

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!


Please do not use the comment function to ask for help! If you need help, please use our forum.
Comments will be published after administrator approval.
Submitted by Paul Theodoropoulos (not registered) on Thu, 2014-08-07 01:14.

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!

Submitted by colapsar (registered user) on Tue, 2014-02-25 04:48.
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

 

 

Submitted by Some_Bored_Dude (registered user) on Mon, 2012-06-18 07:32.

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.

Submitted by counterpoint (registered user) on Sun, 2013-05-26 14:40.
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.
Submitted by Anonymous (not registered) on Tue, 2012-12-18 09:21.
i have not libgost.so file, what can i do?
Submitted by inferion79 (registered user) on Wed, 2007-11-21 22:53.

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 

Submitted by Anonymous (not registered) on Wed, 2005-11-16 09:58.

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

Submitted by Anonymous (not registered) on Fri, 2005-11-18 23:11.
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 :)
Submitted by admin (registered user) on Sat, 2005-11-19 12:30.
Thanks for the hint. I've corrected the bug. :-)
Submitted by Anonymous (not registered) on Fri, 2005-10-28 08:10.

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

Submitted by tagammeer (registered user) on Tue, 2005-11-01 01:33.

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!

Submitted by admin (registered user) on Tue, 2005-11-01 09:52.
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.

Submitted by Anonymous (not registered) on Fri, 2005-10-28 10:02.

Sorry, the above should read:

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

t. ir

Submitted by Anonymous (not registered) on Tue, 2005-12-13 15:35.

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

Should read:

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

Submitted by Anonymous (not registered) on Wed, 2006-01-18 05:04.

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!

Submitted by Anonymous (not registered) on Sun, 2006-01-29 20:50.

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.

Submitted by Anonymous (not registered) on Wed, 2006-05-17 22:31.
good thing you mentioned it.