MadCamel's way of doing a chroot BIND9 install on FreeBSD and Linux Version 1.4 Thu May 13 12:56:55 EDT 2004 Rationale: I don't trust 9's built-in chroot. It's ISC after all. This is MY way. Sure there are other chroot BIND docs.. But doing it (almost) this way since BIND 8.2 I have never gotten owned via BIND. YMMV! Get a copy of latest BIND src, untar and build: ./configure --prefix=/; make Make a directory for it to live in (Mine's /home/chroot/bind) and install: make install DESTDIR=/home/chroot/bind Make a user+group for it, mine's called 'bind' and has a uid/gid of 53 We need to populate the chroot with the proper libraries. This is dependant on platform.. ldd /home/chroot/bind/sbin/named to see what libraries it needs, and copy them in to the chroot in their respective places. I'm using FreeBSD so I do the following: --SNIP-- root@janes:/home/chroot/bind# ldd sbin/named sbin/named: libc.so.4 => /usr/lib/libc.so.4 (0x28199000) root@janes:/home/chroot/bind# mkdir -p usr/lib root@janes:/home/chroot/bind# cp /usr/lib/libc.so.4 usr/lib --SNIP-- PWD=/home/chroot/bind from here down unless otherwise noted. It doesn't say it in ldd, but FreeBSD also needs /usr/libexec/ld-elf.so.1 to link properly (On Linux ldd tells you everything it needs), so: mkdir -p usr/libexec; cp /usr/libexec/ld-elf.so.1 usr/libexec Linux only: You need to make an etc/ld.so.cache file: cp /sbin/ldconfig .; mkdir etc; chroot . /ldconfig -v; rm ldconfig If you have installed all the libraries properly, the following test should succeed: --SNIP-- root@janes:/home/chroot/bind# chroot . /sbin/named -h usage: named [-c conffile] [-d debuglevel] [-f|-g] [-n number_of_cpus] [-p port] [-s] [-t chrootdir] [-u username] --SNIP-- Ok so we have named.. what next? We need to make an /etc and a /dev for named to work right. Start with etc by filling out passwd and group so BIND can look up it's own username (remember that user we made?): mkdir -f etc; grep bind /etc/group >etc/group; grep bind /etc/passwd >etc/passwd On FreeBSD you also need to grep bind /etc/master.passwd >etc/master.passwd and pwd_mkdb -d etc/ etc/master.passwd On Linux you will need /etc/nsswitch.conf: cp /etc/nsswitch.conf etc/ Now /dev, we need to make /dev/null and /dev/urandom: (add a -dp to the flags on linux) mkdir dev; cp -R /dev/null dev; cp -R /dev/urandom dev Logging is next. This is the most system dependant out of everything in my opinion. You need to know how your OS's libc syslog() function works. On FreeBSD it writes to a log socket in /var/run/log, in Linux /dev/log. Depending on your syslogd, you can either add an extra log socket to the syslogd commandline in your startup scripts (-a /home/chroot/bind/dev/log for linux sysklogd), or use a syslog proxy. My syslog proxy is availible at http://coder.home.cosmic-cow.net/src/logproxy.c. Any way you do it, the object is to get logging working by making sure there is a log socket in the proper location for your OS that somehow gets back to the normal syslogd outside of the chroot. For the truely anal-retentive you could also setup a syslog server INSIDE the chroot, however I prefer to keep my logs consolidated. Both FreeBSD and Linux users should just be able to compile and run logproxy with the path to the log socket in the BIND root as an argument (don't forget to put it in system startup).. FreeBSD Example: mkdir -p var/run; logproxy /home/chroot/bind/var/run/log You need to have a way to control this BIND instance. Run sbin/rndc-keygen -c /dev/urandom, paste the rndc.conf section into /etc/rndc.conf (the real /etc) and chown root:root chmod og-rwx it Paste the named.conf section into your named.conf (Or in my case named.options) Then cp sbin/rndc /usr/local/sbin We need to make a directory for zones to live in, and chown it to bind:bind: mkdir zone; chown bind:bind zone We need to make var/run writeable by the bind user: chown bind:bind var/run Ok. BIND has a happy environment to live in :) Lets do some configurating. The following is a sanitized dump of my configuration. It lives in /home/chroot/bind/. You should Know about db.root and db.local if you are a DNS admin. --SNIP-- options{ directory "/zone/"; version "ScriptKiddie v1.0"; // Security. Who can transfer zone files from us allow-transfer { 192.168.0.0/24; // Our subnet 10.1.1.1; // Our secondary NS ! 0/0; // Nobody else }; // Security. Who can use us to lookup hosts // Note that this is overidden below in the zones to allow // us to act as a NS for those domains. allow-query { 127.0.0.1; 192.168.0.0/24; // Our subnet !0/0; // Nobody else }; // Notify peers of zone updates notify yes; cleaning-interval 120; // Running out of entropy is BAD mmkay? random-device "/dev/urandom"; }; /* rndc stuff */ key "rndc-key" { algorithm hmac-md5; secret "SuperSecretKeyHaHa"; }; controls { inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { "rndc-key"; }; }; zone "." { type hint; file "/zone/db.root"; }; zone "0.0.127.in-addr.arpa" { type master; file "/zone/db.local"; }; /* Verisign can bite my shiny metal ass! */ zone "net" { type delegation-only; }; zone "com" { type delegation-only; }; /* Our main domain */ zone "cosmic-cow.net" { type master; file "cosmic-cow.net"; allow-query { any; }; }; --SNIP-- Starting is easy: chroot /home/chroot/bind/ /sbin/named -u bind -c /named.conf Check your syslog, you should be good to go. You may wish to tighten down file permissions so only root and the bind user can read anything under /home/chroot/bind. I recommend doing so. At least named.conf so your rndc key isn't wide open allowing any local user to stop the nameserver :) On FreeBSD you should look in to using the jail command instead of chroot, it's tighter. If this has been a help to you, Good! If not, bite me.