Chrooting Apache Webserver using Mod Security

Howto chroot apache web server using the mod_security extension.

This howto is based on Gentoo but should be fairly easily adoptable to any other linux distribution.

Getting started

It is assumed your chroot will be created in /svr/www . Adopt accordingly. First install apache and mod_security emerge -av apache mod_security

create the chroot directory, e.g. /svr/www and the directory for the pid file mkdir -p /svr/www/var/run

Configuring apache web server

Not much to do here. Just make sure to exclude the chroot directory in all your vhost config files and the DocumentRoot setting. E.g. If your chroot is /svr/www and your website is located in /svr/www/htdocs/mywebsite set DocumentRoot to /htdocs/mywebsite.

In /etc/conf.d/apache2 make sure your APACHE2_OPTS variable contains -D SECURITY and add PIDFILE=/svr/www/var/run/apache2.pid

Configuring ModSecurity

In /etc/apache2/modules.d/79_modsecurity.conf add to the section SecChrootDir /svr/www

Basically that’s it!

However you might experience some minor annoying things with this very basic configuration. So here are the problems I got and how I fixed them.

Fixing init script not killing apache

Your init script will probably try to stop apache and eventually time out or complain about a missing pid file.

add to /etc/apache2/modules.d/79_modsecurity.conf

PidFile /svr/www/var/run/apache2.pid

and in your /etc/init.d/apache2 script change the stop command. You should find some line like

${APACHE2} ${APACHE2_OPTS} -k stop

this needs to be changed by adding -D STOP e.g.

${APACHE2} ${APACHE2_OPTS} -D STOP -k stop

Mounting the mysql socket inside the chroot

You will probably run apache with mod_php or mod_python which need access to your favourite sql server.

For MySQL/MariaDB first create the corresponding directory:

mkdir /svr/www/var/run/mysqld

Edit your mysql init script (/etc/init.d/mysql) to bind the socket into your apache chroot.

mount --bind /var/run/mysqld/mysqld.sock /svr/www/var/run/mysqld/mysqld.sock

This command should do the job. Add it somewhere to the bottom of the start function after it was ensured mysql has actually been started. You can have a look at the modified mysql init script in this article: Chrooting MySQL and MariaDB

I also had to create a dummy file to mount the socket on. Not sure if this is intentional or a bug in mount.

touch /svr/www/var/run/mysqld/mysqld.sock

Resolving DNS

If you have scripts which need DNS resolving you have to copy another lib:

cp /lib/libnss_dns.so.2 /svr/www/lib/

cp /etc/{hosts,resolve.conf} /svr/www/etc/

Sending emails

To be able to send emails you need to have a sendmail-compatible program inside the chroot. Again, this is only needed if you run dynamic scripts like mod_php/mod_python/mod_whatever. You could use ssmtp because it’s lightweight :

euse -p mail-mta/ssmtp -D mta ssl ipv6 && emerge -av mail-mta/ssmtp

mkdir /svr/www/{bin,lib,etc}

cp /lib/{ld-linux-x86-64.so.2,libc.so.6} /svr/www/lib

cp /usr/sbin/ssmtp /svr/www/bin/sendmail

cp -r /etc/ssmtp /svr/www/etc/ssmtp

now simply edit the ssmtp.conf inside the chroot to reference a valid smtp server (e.g. 127.0.0.1:25).

Contact Us

We'd be thrilled to help your company – small or large – deliver products that better serve your customers' goals.