Chroot/Dnsmasq
From Gentoo Linux Wiki
| Installation • Kernel & Hardware • Networks • Portage • Software • System • X Server • Gaming • Non-x86 • Emulators • Misc |
Contents |
[edit] Introduction
[edit] Purpose
This document describes, how you can put dnsmasq in a chroot jail. Under normal circumstances one won't need this, because the program serves only trusted local LAN clients, and no one gets access from the internet.
But maybe someone runs dnsmasq which gets accessed from untrusted clients. There may happen an attack from a cracked server from the DMZ. Other scenarios like an open W-LAN are possible. Putting dnsmasq in a chroot jail should make your server a bit more secure
[edit] Scope
This HOWTO gives some expansion to the dnsmasq boot scripts, so dnsmasq is automatically put in chroot on startup. The document refers to version 2.22 of dnsmasq in the Gentoo repository.
[edit] Acronyms
- DMZ
- De-Militarized Zone
[edit] Setup
[edit] Requirements
You need to emerge dnsmasq:
emerge -a dnsmasq
The chroot command used is already included in Gentoo
[edit] 1st test
At first test, if your service is running properly. Start the service by running
/etc/init.d/dnsmasq start
and do some queries with "host" or "dig" directed to your nameserver. You need to make sure, that your services like DNS or DHCP work this way to get a testcase to compare to the chrooted service.
NOTE: It may be obvious, but during this time, your service is running without chroot restrictions. Take any steps needed to prevent access from untrusted clients.
Now stop the service and go on with setting up the chroot environment.
[edit] Setup the environment
Next is trying to put the program in a chroot jail. Make up a decent directory (e.g. /chroot/dnsmasq/) and copy the configurations file and runtime libs into, along with the related path. The directory tree should look like this afterwards
/chroot/dnsmasq/etc
/chroot/dnsmasq/etc/dnsmasq.conf
/chroot/dnsmasq/etc/hosts
/chroot/dnsmasq/etc/ppp
/chroot/dnsmasq/etc/ppp/resolv.conf
/chroot/dnsmasq/etc/passwd
/chroot/dnsmasq/etc/nsswitch.conf
/chroot/dnsmasq/etc/group
/chroot/dnsmasq/etc/localtime
/chroot/dnsmasq/etc/passwd.bak
/chroot/dnsmasq/etc/group.bak
/chroot/dnsmasq/etc/resolv.conf.bak
/chroot/dnsmasq/var
/chroot/dnsmasq/var/lib
/chroot/dnsmasq/var/lib/misc
/chroot/dnsmasq/var/lib/misc/dnsmasq.leases
/chroot/dnsmasq/var/db
/chroot/dnsmasq/var/run
/chroot/dnsmasq/var/run/dnsmasq.pid
/chroot/dnsmasq/usr
/chroot/dnsmasq/usr/sbin
/chroot/dnsmasq/usr/sbin/dnsmasq
/chroot/dnsmasq/lib
/chroot/dnsmasq/lib/libc.so.6
/chroot/dnsmasq/lib/ld-linux.so.2
/chroot/dnsmasq/lib/libnss_compat.so.2
/chroot/dnsmasq/lib/libnsl.so.1
To test the setup, call dnsmasq in the chroot environment with your usual options and check its running, e.g.
chroot /chroot/dnsmasq /usr/sbin/dnsmasq --user=named --group=named
Check that all needed libs are provided and the directories got write access where needed.
[edit] Expanding the boot scripts
Your boot script now does the same like in the test, execpt it tests for a valid environment, and copies all libs and config files to the chroot directory. If you did compile some libs anew e.g. during emerge -uD world, you only need to restart your service to get the new libs and binaries in the chroot dir.
| File: /etc/init.d/dnsmasq |
#!/sbin/runscript
# Copyright 1999-2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License, v2 or later
# $Header: /var/cvsroot/gentoo-x86/net-dns/dnsmasq/files/dnsmasq-init,v 1.8 2006
/01/09 12:21:39 avenj Exp $
opts="${opts} reload"
depend() {
provide dns
need net
}
checkconfig() {
# test for chroot env
if [ "${DNSMASQ_USE_CHROOT}" == "yes" ] ; then
if [ -z "${DNSMASQ_CHROOT_DIR}" ] ; then
eerror "You specified dnsmasq to run with chroot,"
eerror " but didn't give a directory in DNSMASQ_CHROOT_DIR."
eerror "Please update /etc/conf.d/dnsmasq"
return 1
fi
if [ ! -d ${DNSMASQ_CHROOT_DIR} ] ; then
eerror "\"${DNSMASQ_CHROOT_DIR}\" is no directory."
eerror "Please update DNSMASQ_CHROOT_DIR in /etc/conf.d/dnsmasq"
return 1
fi
if [ "`/bin/ls -id ${DNSMASQ_CHROOT_DIR}/ | /bin/cut -d' ' -f1`" == "`/bin/ls -id / | /bin/cut -d' ' -f1`" ] ; then
eerror "\"${DNSMASQ_CHROOT_DIR}\" points to root directory."
eerror "Please update DNSMASQ_CHROOT_DIR in /etc/conf.d/dnsmasq"
return 1
fi
if [ -z "${DNSMASQ_USER}" ] ; then
eerror "You have to give a user, else chroot makes no sense."
eerror "Please update DNSMASQ_USER in /etc/conf.d/dnsmasq"
return 1
fi
if ! /bin/id ${DNSMASQ_USER} > /dev/null 2>&1 ; then
eerror "Unknown user \"${DNSMASQ_USER}\"."
eerror "Please update DNSMASQ_USER in /etc/conf.d/dnsmasq"
return 1
fi
if [ -n "${DNSMASQ_GROUP}" ] ; then
if ! /bin/cut -d ':' -f1 /etc/group | /bin/grep -wq ${DNSMASQ_GROUP} ; then
eerror "Group ${DNSMASQ_GROUP} no found."
eerror "Please update DNSMASQ_GROUP in /etc/conf.d/dnsmasq"
return 1
fi
fi
fi
}
start() {
local ret
if ! checkconfig ; then
eend 1
return 1
fi
if [ "${DNSMASQ_USE_CHROOT}" == "yes" ] ; then
ebegin "Starting dnsmasq in chroot environment"
# make a symlink to find it later on
/bin/ln -sf ${DNSMASQ_CHROOT_DIR}/var/run/dnsmasq.pid /var/run/dnsmasq.pid
# get uid and gid
DNSMASQ_OPTS="${DNSMASQ_OPTS} --user=${DNSMASQ_USER}"
if [ -z "${DNSMASQ_GROUP}" ] ; then
DNSMASQ_GROUP="`/bin/id -gn ${DNSMASQ_USER}`"
fi
DNSMASQ_OPTS="${DNSMASQ_OPTS} --group=${DNSMASQ_GROUP}"
# prepare chroot env
# make directories
for A in /etc/ppp /lib /usr/sbin; do
if [ ! -d ${DNSMASQ_CHROOT_DIR}/${A} ] ; then
if ! /bin/mkdir -p ${DNSMASQ_CHROOT_DIR}/${A} ; then
eerror "Can not create directory ${DNSMASQ_CHROOT_DIR}/${A}. Bailing out"
eend 1
return 1
fi
fi
done
# copy files
#for A in /etc/dnsmasq.conf /etc/localtime /etc/hosts /etc/nsswitch.conf /etc/resolv.conf ; do
for A in /etc/dnsmasq.conf /etc/localtime /etc/hosts /etc/nsswitch.conf ; do
if ! /bin/cp -aLf ${A} ${DNSMASQ_CHROOT_DIR}/etc/. ; then
eerror "Can not copy \"${A}\" to ${DNSMASQ_CHROOT_DIR}/etc/. Bailing out"
eend 1
return 1
fi
done
#if ! /bin/cp -aLf /etc/dnsmasq.d/resolv.conf ${DNSMASQ_CHROOT_DIR}/etc/dnsmasq.d/. ; then
# eerror "Can not copy \"/etc/dnsmasq.d/resolv.conf\" to ${DNSMASQ_CHROOT_DIR}/etc/dnsmasq.d/. Bailing out"
# eend 1
# return 1
#fi
for A in /lib/ld-linux.so.2 /lib/libc.so.6 /lib/libnsl.so.1 /lib/libnss_compat.so.2 ; do
if ! /bin/cp -aLf ${A} ${DNSMASQ_CHROOT_DIR}/lib/.; then
eerror "Can not copy \"${A}\" to ${DNSMASQ_CHROOT_DIR}/lib/. Bailing out"
eend 1
return 1
fi
done
# again test for chroot dir in "/"
# this is a security measure to prevent stipping /etc/passwd of root account
if [ "`/bin/ls -id ${DNSMASQ_CHROOT_DIR}/ | /bin/cut -d' ' -f1`" == "`/bin/ls -id / | /bin/cut -d' ' -f1`" ] ; then
eerror "\"${DNSMASQ_CHROOT_DIR}\" points to root directory."
eerror "In danger of erasings parts of the password data base, exiting"
eend 1
return 1
fi
if [ -f ${DNSMASQ_CHROOT_DIR}/etc/passwd ] ; then
/bin/mv -f ${DNSMASQ_CHROOT_DIR}/etc/passwd ${DNSMASQ_CHROOT_DIR}/etc/passwd.bak
fi
/bin/grep -w ${DNSMASQ_USER} /etc/passwd > ${DNSMASQ_CHROOT_DIR}/etc/passwd
if [ -f ${DNSMASQ_CHROOT_DIR}/etc/group ] ; then
/bin/mv -f ${DNSMASQ_CHROOT_DIR}/etc/group ${DNSMASQ_CHROOT_DIR}/etc/group.bak
fi
/bin/grep -w ${DNSMASQ_GROUP} /etc/group > ${DNSMASQ_CHROOT_DIR}/etc/group
/bin/cp -aLf /usr/sbin/dnsmasq ${DNSMASQ_CHROOT_DIR}/usr/sbin/.
# temporary disable socket create restriction
if [ -w /proc/sys/kernel/grsecurity/chroot_caps ]; then
echo 0 > /proc/sys/kernel/grsecurity/chroot_caps
fi
# start in chroot
/bin/chroot ${DNSMASQ_CHROOT_DIR} /usr/sbin/dnsmasq -x /var/run/dnsmasq.pid ${DNSMASQ_OPTS}
ret=$?
# reenable socket create restriction
if [ -w /proc/sys/kernel/grsecurity/chroot_caps ]; then
sleep 1
echo 1 > /proc/sys/kernel/grsecurity/chroot_caps
fi
else
ebegin "Starting dnsmasq"
/usr/sbin/dnsmasq -x /var/run/dnsmasq.pid ${DNSMASQ_OPTS}
ret=$?
fi
eend $ret
}
stop() {
ebegin "Stopping dnsmasq"
start-stop-daemon --stop --quiet --pidfile /var/run/dnsmasq.pid
# remove maybe dangling symlink from chroot environment
/bin/rm -f /var/run/dnsmasq.pid
eend $?
}
reload() {
ebegin "Reloading dnsmasq"
kill -HUP $(< /var/run/dnsmasq.pid)
eend $?
}
|
[edit] Configuration
Now change your configuration to run as user "named". Else your chroot setup wouldn't make much sense.
| File: /etc/conf.d/dnsmasq |
# /etc/conf.d/dnsmasq: config file for /etc/init.d/dnsmasq # See the dnsmasq(8) man page for possible options to put here. DNSMASQ_OPTS="" # user & group replacement DNSMASQ_USER="named" DNSMASQ_GROUP="named" # run in chroot env DNSMASQ_USE_CHROOT="yes" # only valid if DNSMASQ_USE_CHROOT==yes above # # chroot dir DNSMASQ_CHROOT_DIR="/chroot/dnsmasq/" |
Dnsmasq has to know the position of the resolv.conf file.
In this HOWTO I put it in /chroot/dnsmasq/etc/ppp/resolv.conf, but you can put it anywhere in the chrooted directory.
Just let dnsmasq know where it is
| File: /etc/dnsmasq.conf |
# Change this line if you want dns to get its upstream servers from # somewhere other that /etc/resolv.conf # NOTE: dont specify 2 files #resolv-file=/etc/resolv.conf resolv-file=/etc/ppp/resolv.conf |
Here we don't put in the full path, more then the relative one to the chroot dir. This is because the chroot() syscall happens before the execution of dnsmasq, so it just sees "/chroot/dnsmasq" as "/"
[edit] Finish
Now start your service in chroot and add it to the boot sequence
/etc/init.d/dnsmasq start rc-update add dnsmasq default
You're done!
