Tuesday, October 27, 2015

BIND with chroot on 14.04LTS

The Task

Today I was tasked with migrating a public DNS server from Fedora Core 3 (yea FC3. I know today's date. I gagged too). The flavor of choice here is Ubuntu, not my first choice for enterprise production systems but it's not worth the fight for a simple DNS server. There is some debate about whether BIND needs to run out of chroot or not, especially on a dedicated virtual server that serves no other purpose, what's the worst that could happen? I erred on the side of "this is how I've always done it, it can't hurt to keep doing it". Besides, this system might be dedicated to DNS today but who knows what tomorrow will bring. Here's how I configured BIND in a chroot on Ubuntu 14.04LTS

How I Did It

First, I followed my standard minimal Ubuntu LTS install and got it to authenticate to Active Directory.

On to the meat of the procedure, installing BIND is a snap.
$ sudo apt-get install bind9

Unfortunately Ubuntu thinks we want BIND to start right away and doesn't have a neat bind-chroot package, so next we'll stop it and move some stuff around.
$ sudo service stop bind

Now we can start setting up the chroot, first telling BIND that's what we're going to do by specifying the chroot as a startup option in /etc/default/bind9
$ sudo sed s/\-\ u\ bind\ \-\ t/\-\ u\ bind\ \-\ t\ \/var\/named\/chroot/g /etc/default/bind9

Next we'll create the chroot directory structure
$ sudo mkdir -p /var/named/chroot/{dev,etc,var/{cache/bind,run/bind/run,},usr/lib/x86_64-linux-gnu/openssl-1.0.0/engines}

Now move bind into the chroot and make a symlink for it's original location so updates will find there way into the chroot
$ sudo mv /etc/bind /var/named/chroot
$ sudo ln -s /var/named/chroot/etc/bind /etc/bind

Create the null and random devices
$ sudo mknod /var/named/chroot/dev/null c 1 3
$ sudo mknod /var/named/chroot/dev/random c 1 8
$ sudo chmod 666 /var/named/chroot/dev/*

And change the owner of everything to bind:bind
$ sudo chown -R bind:bind /var/named/chroot

You notice we made a directory for openssl, BIND needs a couple of things from OpenSSL. To get those things we're going to mount part of the file system back to itself so when OpenSSL is updated, this will be too.
$ echo "/usr/lib/x86_64-linux-gnu/openssl-1.0.0/engines /var/chroot/named/usr/lib/x86_64-linux-gnu/openssl-1.0.0/engines none defaults,bind,auto,nodev,noexec,nosuid 0 0" | sudo tee -a /etc/fstab
$ sudo mount !$

BIND also needs to use /dev/log so we need to setup a new syslog socket inside the chroot.
$ echo "$AddUnixListenSocket /var/named/chroot/dev/log" | sudo tee /etc/rsyslog.d/60-bind-chroot.conf
$ sudo service rsyslog restart

Finally update AppArmor to allow reads on the things BIND needs from OpenSSL
$ echo "/var/named/chroot/usr/lib/x86_64-linux-gnu/openssl-1.0.0/engines/libgost.so rm," | sudo tee -a /etc/apparmor.d/local/usr.sbin.named
$ echo "/var/named/chroot/etc/bind r," | sudo tee -a /etc/apparmor.d/local/usr.sbin.named
$ sudo service bind9 reload

That's it, start BIND and test! All that is left for me is to move the config and zones from the old server to the new one and have the network boys move the NAT.
$ sudo service bind9 start
$ dig +short A www.google.com @localhost
173.194.121.48
173.194.121.52
173.194.121.49
173.194.121.51
173.194.121.50