These variables should be specified in the
Makefile.set for your port (e.g., if you use
Solaris, in src/port/solaris/Makefile.set).
So the file I wanted was
src/port/freebsd/Makefile.set. Here is what
the original looked like:
'CC=cc'
'CDEBUG=-O2 -g'
'DESTBIN=/usr/bin'
'DESTSBIN=/usr/sbin'
'DESTEXEC=/usr/libexec'
'DESTMAN=/usr/share/man'
'DESTHELP=/usr/share/misc'
'DESTETC=/etc'
'DESTRUN=/var/run'
'LEX=lex -I'
'YACC=yacc -d'
'SYSLIBS=-ll -lutil'
'INSTALL=install'
'MANDIR=cat'
'MANROFF=(tbl|nroff -man)'
'CATEXT=0'
'PS=ps'
'RANLIB=ranlib'
A quick edit of this file enabled me to test compile
BIND to run in /tmp/named, and to do a
static compile. At this stage, I did plenty of
fact-finding. I'll spare you the full details because
it's mostly boring. Besides, this article is supposed
to detail "how to do it" without the tedious messing
about that I was forced to do.
I realized several things quite early on in my
trials:
The only thing that should go into the jail
was named(8) and named-xfer(8). As
far as these two were concerned they would happily
run inside my chroot jail with absolutely no changes
to the build configuration. The only thing I had
to get right was the directory structure.
Everything else (namely dig(1),
host(1), and nslookup(8)) would
happily run in the standard locations.
The only thing that needed to run outside the
jail, but need to know all about inside the jail,
was ndc(8). I knew this would be a massive
headache, so I left this until last.
It would be a much easier to get BIND running
outside the jail first.
So, having played and thought about it, I wrote down
my plan of action:
Download and extract the latest BIND
sources.
Do a static compile and install.
Get named(8) running normally.
Build the chroot hierarchy, and populate
it.
Force syslogd(8) to work with
named(8).
Get named(8) running chrooted and set
it to run at boot time.
Stop make world from clobbering it.
Fix ndc(8).
Tidy up.
So to business, here is how you get bind-8.2.3 running
on a box running FreeBSD 4.2-STABLE.
Note: From here on in everything
gets done as root. So take care not to break
things.
Download
I used wget
to download the sources. You may not have wget installed,
but I'm sure you can work out how to download one file.
Here is what I did (using fetch(1) instead of
wget will also work):
# wget ftp://ftp.isc.org/isc/bind/src/8.2.3/bind-src.tar.gz
And once this had finished:
# tar xvzf bind-src.tar.gz
This creates the directory src, and in
this directory you will find all things BIND. BIND
documention comes in a seperate tarball so if you want
that too you have to work it out for yourself.
The Static Compile
This is easy. Edit the file
src/port/freebsd/Makefile.set and change the
line:
'CDEBUG=-O2 -g'
to:
'CDEBUG=-O2 -g -static'
Now, change into the src directory and run
these commands one at a time:
# make clean
# make depend
# make
# make install
This will compile and install a static copy of the
BIND distribution.
Get named running normally
The base FreeBSD install includes BIND. So most of
the files you will need are to be found in
/etc/namedb.
You will need to generate the file
localhost.rev. This is simple:
# cd /etc/namedb
# sh make-localhost
You will also need to create your named.conf
file. The installed named expects to find it's
configuration in /etc/namedb. The newly
compiled named expects to find it in /etc.
You could copy (or link) /etc/namedb/named.conf
to /etc/named.conf, however, the included
file is a sample and it will need editing so it is
actually much easier to create one from scratch. Here
is a simple config that will allow named to run a simple
caching only nameserver.
options {
directory "/etc/namedb";
query-source address * port 1024;
};
zone "." {
type hint;
file "named.root";
};
zone "0.0.127.IN-ADDR.ARPA" {
type master;
file "localhost.rev";
};
This is fine for testing, and is easily expanded
later.
You can now start named(8). However, I like
named to log via syslog. So, before starting named add
this to the end of /etc/syslog.conf:
!named
*.* /var/log/named.log
Then run these commands:
# touch /var/log/named.log
# killall -HUP syslogd
Now start named(8):
# /usr/sbin/named -u bind -g bind
The -u bind -g bind tells named to run as
user bind and group bind. You
don't have to create this user and group, they come as
part of the base install.
Use dig(1) to verify that everything is
working:
# dig www.freebsdzine.org @localhost
Now kill named(8):
# ndc stop
Build & Populate the Chroot Hierarchy
I've chosen to make my "chroot root"
/usr/chroot/named. Put your "root" anywhere
you like, but bear in mind all instructions refer to
my location.
Now it's time to make the directories that are
needed. Do the following:
# mkdir /usr/chroot/named
# cd /usr/chroot/named
# mkdir dev etc usr usr/libexec usr/sbin var var/run
Now move named(8), named-xfer(8),
and your configuration files into their new homes:
# mv /usr/sbin/named usr/sbin/
# mv /usr/libexec/named-xfer usr/libexec/
# mv /etc/named.conf etc/
# mv /etc/namedb etc/
Additionally, in order to run, named(8)
requires /dev/null to exist within in the
chroot directory hierarchy. I discovered how to do
this by reading /dev/MAKEDEV.
Here is what you need to do:
# cd dev
# mknod null c 2 2
# chmod 0666 null
Named & Syslog
The original helpful advice from the BIND source
stated:
syslog() is often troublesome after chrooting.
Use the "logging" statement and log to a file
instead.
If you were to pay attention to this then you can
simply fire up named(8) now. It'll work - it
just won't use syslog. However getting syslog and
named(8) to work together is not actually that
hard. All you need to do is get syslogd(8) to
create an additional log socket somewhre that named can
find it. The syslogd(8) man page states that
the -l option can be used to:
Specify a location where syslogd should place an
additional log socket. Up to 19 additional logging
sockets can be specified. The primary use for this
is to place additional log sockets in
/var/run/log of various chroot
filespaces.
So according to this man page fragment, running
syslogd(8) like this:
# syslogd -l /usr/chroot/named/var/run/log
The above will create an additional UNIX domain
socket where named can find it, and thereby allow
logging via syslog. Alas, whereas this is correct,
it's only half correct. The syslog functions uses
/dev/log which is a symlink to
/var/run/log. I've no idea why it's done
like this, but on the assumption it's done like this
for a good reason...
# killall syslogd
# syslogd -l /usr/chroot/named/var/run/log
# cd /usr/chroot/named/dev
# ln -fs /var/run/log
Note how the symlink will actually work both inside
and outside the chroot jail.
This will allow syslog to listen to named(8),
but the timestamps will be wrong. In order to get
time working correctly you have to:
# cp /etc/localtime /usr/chroot/named/etc/
You also have to ensure syslog starts with the correct
options at boot time. Simply edit /etc/rc.conf
and add the line:
syslog_flags="-l /usr/chroot/named/var/run/log"
Starting named
Starting your chrooted named(8) is now easy.
Just enter this command:
# /usr/chroot/named/usr/sbin/named -u bind -g bind -t /usr/chroot/named/
Starting named(8) automatically on boot is easy
too. Simply edit /etc/rc.conf and add the
following lines:
named_enable="YES"
named_program="/usr/chroot/named/sbin/named"
named_flags="-u bind -g bind -t /usr/chroot/named"
Stop make world from clobbering it
As you are no doubt aware BIND is included with
FreeBSD, and it's also included in the source tree.
So doing a make world will install a new copy of
named(8), and likely clobber your carefully
chrooted copy. To stop this from happening edit
/etc/make.conf and put the following line in
it:
NO_BIND= true
Fix ndc
Working out how to get ndc(8) to work with a
chrooted named(8) was fairly hard. This was
mainly because I was working with a clean copy of the
sources. I then discovered that the make depend stage
of the compilation process created an include file
called pathnames.h. And it is this file
that requires mangling.
Change directories to your named sources, then:
# cd bin/ndc
Now open pathnames.h into your favorite
editor. There are many definitions in this file, but
only 3 of these are used in the ndc(8)
source:
_PATH_NAMED
_PATH_PIDFILE
_PATH_NDCSOCK
Each of these needs to be edited to point to inside
your chroot root. You need to change the
following:
#define _PATH_NDCSOCK "/var/run/ndc"
should be changed to:
#define _PATH_NDCSOCK "/usr/chroot/named/var/run/ndc"
And change:
#define _PATH_PIDFILE "/var/run/named.pid"
to:
#define _PATH_PIDFILE "/usr/chroot/named/var/run/named.pid"
Simply adding the path to the _PATH_NAMED
definition, however, is not sufficient. When you run
ndc start and ndc restart, you
need to ensure named(8) is passed the correct
options to cause it to run as the correct user, in the
correct group, and to chroot to the correct directory.
Hence this definition:
#define _PATH_NAMED "/usr/sbin/named"
needs to be changed to:
#define _PATH_NAMED "/usr/chroot/named/usr/sbin/named -u bind -g bind \
-t /usr/chroot/named/"
Once you have made these changes compile and install
your modified ndc(8):
# make
# install -s -c -m 755 ndc /usr/sbin/ndc
Note: Running "make install" will
install ndc(8) in /usr/local/sbin
which is not where we want it.
Now check your log file and restart named(8):
In one terminal do:
# tail -f /var/log/named.log
And in another do:
# ndc restart
If you've done things right, you should see messages
including:
chrooted to /usr/chroot/named/
group = bind
user = bind
Ready to answer queries.
So now ndc works. But, you still have to be root to
run it. A little trick I use is this:
# chmod o-x,u+s /usr/sbin/ndc
Which will allow anyone in the "wheel" group to run
ndc(8) as root. However, this does have
security implications so only do this if you are
prepared to accept the concequences.
Finishing touches
Okay, named is installed and running in it's chroot jail.
It starts up at boot time, and you can control it with
ndc(8). However, there are a couple of things
I feel still need to be done.
Personally I'd put a note in /etc/motd. I
mainly do this because I've got a problem with my
short-term memory, but it also helps others who may have
to do some DNS admin.
Also, I'd place a couple of symlinks in
/etc:
# cd /etc
# ln -s /usr/chroot/named/etc/named.conf
# ln -s /usr/chroot/named/etc/namedb
Because even though I've left a message, most people
won't read it (after all I know I won't). So putting a
link where everyone expects to find named config files
makes the chrooting almost transparent.
And you really should add something like this in
/etc/newsyslog.conf:
/var/log/named.log 644 3 * $W0D23 Z
If you don't, /var is going to fill up one
day.
Oh yes, if you plan to provide secondary DNS, the slave
directory needs to be writeable by the bind user:
# mkdir etc/named/s
# chown bind:bind etc/named/s
Finally, delete your sources if you feel you don't
need them any more.
Oh yes, one more thing. If you've got named(8)
running on your box, it makes sense to have your resolver
use it. So edit /etc/resolv.conf, comment out
all the existing nameserver entries and add the
line:
nameserver 127.0.0.1
Once you've done all this, sit down, put your feet up
and have a well earned cup of tea. And, if you can think
of something I've forgotten, please let me know.
- Peter
Return to
Issue 1, May 2001