HOWTO build an Apache Security Proxy

From RADION OpenLab

Apache unter Linux als Aufpasser
Enlarge
Apache unter Linux als Aufpasser

Contents

1 Release history

Draft 26.08.2005 Kamil Wencel Official Release for Apache 1.3.33 KamilWencel 19:55, 29 October 2005 (UTC)
Release 1.0 05.09.2005 Kamil Wencel Official Release for Apache 1.3.33 KamilWencel 19:55, 29 October 2005 (UTC)
Release 1.1 27.10.2005 Kamil Wencel Minor Cosmetics 62.245.223.133 15:15, 28 Oct 2005 (UTC)
Release 1.2 29.10.2005 Kamil Wencel Update for Apache 1.3.34 KamilWencel 19:55, 29 October 2005 (UTC)

2 Introduction

It's a shame but it is true : The good old times, when you could build applications without security in mind are gone. As a matter of fact you should consider spending more time on security technology & philosophy than on the actual application itself. You cannot use an application which technically performs its tasks but cannot be deployed in an insecure environment. With that in mind this HOWTO evolved. No matter how much time you invest into making your application secure, there will always be a chance you might forgott something or didn't know better. Therefore you should have some fallback option like an application layer filter in front of your application server ( which might be an apache with php as well ) - that will add a great deal of security, if handled mindfully.

This HOWTO will help you to deploy a jailrooted Apache with ModSecurity, ModSSL and PHP enabled. It will NOT cover all the specifics of PHP configure options or SSL configuration for webservers. If you would like to contribute to these topics write your own HOWTO at RADION Openlabs.

To follow this HOWTO you need at least good basic knowledge of Apache and the way it works. Don't forget that mod_security basically is an Intrusion Detection System ( IDS ) and as such needs a lot of attention regarding the rules. You cannot expect a "fire-and-forget" solution, these rules live and have to have regular maintenance. You will have to tweak a lot to avoid getting caught up in false positives. Sometimes you'll have to disable it at all, because the specific purpose of the site you want to protect always gets trapped within the IDS.

3 What ModSecurity can do for you

In order to add security benefit to your infrastructure you have to know how each and every piece in your security chain works otherwise you will not be able to maintain security. At first glance ModSecurity is just another module for the Apache web server. In the simplest terms ModSecurity offers the following features :

  • ModSecurity checks all in and outgoing HTTP traffic ( GET,POST,HEAD,etc. )
  • Attack patterns to check can be included into a single config file
  • Easy to understand config
  • chroot Apache without the hassle of providing a fully separated environment manually

This HOWTO describes how to setup both, intrusion detection and a chrooted environment.

When chroot mode is enabled you have to understand the startup procedure to not to stumble over configuration issues. When you start Apache the parent process opens all logfiles - which should be located outside of the jailroot from my point of view - and provides internal pointers to these logfiles for its children.

4 Definitions

We used a pretty much default gentoo stage1 system for this HOWTO. None of the packages we want to use were emerged from portage.
We want Apache to run in a JailRoot to lessen the risk of the whole machine becoming compromised.

4.1 General conventions

  • All source files will reside in /usr/local/src/
  • All documents, HTML, PHP, images etc. will go into the JailRoot in /www
  • All logfiles will be in /var/log/apache
  • The apache start / stop script will reside in /etc/init.d/apache
  • Apache will not be installed to /usr but to /usr/local/apache/1.3.39
  • Apache Virtual containers will reside in /www/container/
  • Apache Virtual container logfiles will go respectively into /var/log/apache/container/$containername

4.2 Recommended partitioning and mountpoints

Basically the harddisk is partitioned as follows :

Disk /dev/hda: 160.0 GB, 160041885696 bytes
255 heads, 63 sectors/track, 19457 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hda1   *           1           4       32098+  83  Linux
/dev/hda2               5         129     1004062+  82  Linux swap / Solaris
/dev/hda3             130        1126     8008402+  83  Linux
/dev/hda4            1127       19457   147243757+  83  Linux

and these partitions are mounted as :

/dev/hda1/bootBoot Partition
/dev/hda2swapSwap Partition
/dev/hda3/Root Filesystem
/dev/hda4/wwwApache JailRoot Filesystem

4.3 Considerations

Configuration needs a bit of a split personality. For example while you and your OS will see the path to the container as /www/container/www.mydomain.org is you stick to the recommended configuration of this HOWTO in your hhtpd.conf you'll have to write /container/www.mydomain.org because after loading als its libs and additional modules apache chroots and simply doesn't see anything above /www or /www itself anymore.

5 Recommended hardware

It is hard to forecast which services you are going to offer and how many visitors you may get using them. So the real hardware requirements of your services depend highly on your own estimations. Basically two things you are going to need :

  • As much CPU power as you can get
  • As much RAM as you can get


We also recommend to use SMP ( Multiprocessor ) systems, as especially Apache will benefit from having more CPU's to fork onto. Regarding main memory ( RAM ) you should have at least 1024MB of it and an equally sized swap partition.

Remember, CPU and RAM usage also highly depend on the size of your ModSecurity ruleset and of course : SSL can really drain a machine down because of CPU expensive key calculations. If you plan to use a lot of SSL connections consider buying a SSL hardware accelerator card and dedicate a server for SSL connections only.


6 Required software

The following links will transport you as close to the download as possible. If you want further links regarding the software used, please have a look at the appendix.

6.1 Open Source

Apache 1.3.39 http://httpd.apache.org/download.cgi
PHP 5.2.4 http://www.php.net/get/php-5.2.4.tar.bz2/from/a/mirror
ModSSL http://www.modssl.org/source/
ModSecurity http://www.modsecurity.org/download/index.html
ModGZip http://sourceforge.net/projects/mod-gzip/

6.2 Closed Source

Zend Optimizer http://www.zend.com/store/products/zend-optimizer.php


Put all files you download into /usr/local/src.

7 Unpacking packages

# tar xvfz apache_1.3.39.tar.gz
# tar xvfz mod_ssl-2.8.30-1.3.39.tar.gz
# tar xvfz modsecurity-1.9.5.tar.gz
# tar xvfz mod_gzip-1.3.26.1a.tgz
# tar xvfz ZendOptimizer-2.5.10a-linux-glibc21-i386.tar.gz
# tar xvjpf php-5.2.4.tar.bz2

8 Building required components

8.1 Building Apache

Apache is going to be build to support SSL, PHP, ModSecurity and ModGZip. To achieve that manually without emerging we have to perform several steps in a certain order. We are going to start with ModSSL :

8.1.1 Configure ModSSL in conjunction with Apache

# cd /usr/local/src/mod_ssl-2.8.30-1.3.39

If you are using a gentoo system you'll most likely want to use the same CFLAGS your gentoo system uses to build its packages and copy the CFLAGS out of /etc/make.conf. The CFLAGS used in the example below are working perfectly for us on a x86 Pentium3 ( Dual-Tualatin ) machine.

# CFLAGS="-march=pentium3 -mtune=pentium3 -O3 -pipe -fomit-frame-pointer" \
./configure \
--with-apache=../apache_1.3.39 \
--with-ssl=/usr \
--prefix=/usr/local/apache/1.3.39 \
--datadir=/www \
--enable-module=most \
--enable-shared=max \
--enable-module=ssl \

This should create the following output :

Configuring mod_ssl/2.8.30 for Apache/1.3.39
 + Apache location: ../apache_1.3.39 (Version 1.3.39)
 + OpenSSL location: /usr
 + Auxiliary patch tool: ./etc/patch/patch (local)
 + Applying packages to Apache source tree:
   o Extended API (EAPI)
   o Distribution Documents
   o SSL Module Source
   o SSL Support
   o SSL Configuration Additions
   o SSL Module Documentation
   o Addons
Done: source extension and patches successfully applied.

Configuring for Apache, Version 1.3.39
 + using installation path layout: Apache (config.layout)
Creating Makefile
Creating Configuration.apaci in src
 + enabling mod_so for DSO support
 + configured for Linux platform
 + setting C compiler to gcc
 + setting C pre-processor to gcc -E
 + using "tr [a-z] [A-Z]" to uppercase
 + checking for system header files
 + adding selected modules
    o rewrite_module uses ConfigStart/End
      disabling DBM support for mod_rewrite
      (perhaps you need to add -ldbm, -lndbm or -lgdbm to EXTRA_LIBS)
    o ssl_module uses ConfigStart/End
      + SSL interface: mod_ssl/2.8.30
      + SSL interface build type: DSO
      + SSL interface compatibility: enabled
      + SSL interface experimental code: disabled
      + SSL interface conservative code: disabled
      + SSL interface vendor extensions: disabled
      + SSL interface plugin: Built-in SDBM
      + SSL library path: /usr
      + SSL library version: OpenSSL 0.9.7e 25 Oct 2004
      + SSL library type: installed package (stand-alone)
 + enabling Extended API (EAPI)
 + using system Expat
 + using -ldl for vendor DSO support
 + checking sizeof various data types
 + doing sanity check on compiler and options
Creating Makefile in src/support
Creating Makefile in src/regex
Creating Makefile in src/os/unix
Creating Makefile in src/ap
Creating Makefile in src/main
Creating Makefile in src/modules/standard
Creating Makefile in src/modules/extra
Creating Makefile in src/modules/proxy
Creating Makefile in src/modules/ssl

Now proceed with the following commands:
 $ cd ../apache_1.3.39
 $ make
 $ make certificate
 $ make install

Let's proceed as suggested by the build script to change into Apache's source directory and start compile it.

8.1.2 Compile Apache

If you try to build Apache now it will fail building the mod_auth_dbm module due to a missing ndbm.h header file. However, the file is on the system as part of the gdbm package, but unfortunately it is not located in /usr/inculde but in /usr/include/gdbm/. You can easily tell Apache where to look for it in the standard modules Makefile:

# vi /usr/local/src/apache_1.3.39/src/modules/standard/Makefile

Change the INCLUDES1= into INCLUDES1=-I/usr/include/gdbm/

INCLUDES1=-I/usr/include/gdbm/

Now everything should be alright (at least it was here)

# cd /usr/local/src/apache_1.3.39
# make -j3

the last output should look as follows :

| % make certificate TYPE=existing (existing cert)                    |
|        CRT=/path/to/your.crt [KEY=/path/to/your.key]                |
|                                                                     |
| Use TYPE=dummy    when you're a  vendor package maintainer,         |
| the TYPE=test     when you're an admin but want to do tests only,   |
| the TYPE=custom   when you're an admin willing to run a real server |
| and TYPE=existing when you're an admin who upgrades a server.       |
| (The default is TYPE=test)                                          |
|                                                                     |
| Additionally add ALGO=RSA (default) or ALGO=DSA to select           |
| the signature algorithm used for the generated certificate.         |
|                                                                     |
| Use 'make certificate VIEW=1' to display the generated data.        |
|                                                                     |
| Thanks for using Apache & mod_ssl.       Ralf S. Engelschall        |
|                                          rse@engelschall.com        |
|                                          www.engelschall.com        |
+---------------------------------------------------------------------+
make[1]: Leaving directory `/usr/local/src/apache_1.3.34'
<=== src

As you can see Apache & mod_ssl are already built right now. All we have to do now is to install the files to /usr/local/apache/1.3.39/ by typing make install.

# make install
make[1]: Leaving directory `/usr/local/src/apache_1.3.34'
+--------------------------------------------------------+
| You now have successfully built and installed the      |
| Apache 1.3 HTTP server. To verify that Apache actually |
| works correctly you now should first check the         |
| (initially created or preserved) configuration files   |
|                                                        |
|   /usr/local/apache/1.3.39/conf/httpd.conf
|                                                        |
| and then you should be able to immediately fire up     |
| Apache the first time by running:                      |
|                                                        |
|   /usr/local/apache/1.3.39/bin/apachectl start
|                                                        |
| Or when you want to run it with SSL enabled use:       |
|                                                        |
|   /usr/local/apache/1.3.39/bin/apachectl startssl
|                                                        |
| Thanks for using Apache.       The Apache Group        |
|                                http://www.apache.org/  |
+--------------------------------------------------------+

8.1.3 Rebuild Apache Benchmark to support SSL

Even if you build Apache the way we did before ( prepatching apache's source before the build ) the Apache Benchmark binary "ab" does not support SSL. If you don't need to benchmark your Apache to figure out how much connections your machine can handle you can skip this part and move on to building PHP.

We are going to remedy that disfunction properly by starting to delete the current ab binary :

# cd /usr/local/src/apache-1.3.39/src/support
# rm -f ab

Now we'll have to rebuild ab manually with the following make string to get it to support SSL enablend benchmarks :

# make ab CFLAGS="${CFLAGS} -DUSE_SSL -lcrypto -lssl -I/usr/include/openssl -L/usr/lib" || die
gcc -DUSE_SSL -lcrypto -lssl -I/usr/include/openssl -L/usr/lib -o ab 
-L../os/unix -L../ap ab.o -lm -lap -los  -lm -lcrypt -lndbm -lexpat -ldl

After the binary is build it has to be copied manually into the appropriate apache binary folder :

# cp ab /usr/local/apache/1.3.39/bin/

8.2 Building the PHP Module

# cd /usr/local/src/php-5.2.4

The next step is to build the PHP SAPI Module for Apache and the PHP CLI. The following build string fits our needs - you probably will have different topics to cover so consider this only as an example. You can have a thorough look for yourself on http://www.php.net/manual/en/configure.php where you'll find a list of the most common configure options.

I recommend to build the PHP configure string in a text editor and copy the complete screen into your shell. This way you can always tweak things if your configure screws up and if it doesn't you can instantly copy it into your own documentation. Trust me, after 3 month you'll have forgotten most of the options and you'll be grateful to have some documentation of your own.

If you are using a gentoo system you'll most likely want to use the same CFLAGS your gentoo system uses to build its packages and copy the CFLAGS out of /etc/make.conf. The CFLAGS used in the example below are working perfectly for us on a x86 Pentium3 ( Dual-Tualatin ) machine.


CFLAGS="-march=pentium3 -mtune=pentium3 -O3 -pipe -fomit-frame-pointer" \
./configure --with-apxs=/usr/local/apache/1.3.39/bin/apxs --with-gettext=/usr \
--with-mysql --with-zlib-dir=/usr --enable-calendar --with-freetype-dir=/usr \
--with-zlib=/usr --with-gd --enable-gd-native-ttf --with-config-file-path=/etc \
--with-openssl=/usr \
--enable-sysvshm=yes --enable-sysvsem=yes --enable-sysvmsg --enable-bcmath \
--without-mm --enable-inline-optimization \
--enable-pcntl --enable-sigchild --with-curl --enable-mbstring \
--with-freetype-dir=/usr --enable-exif --with-mcrypt=/usr --with-mhash=/usr 


This should output this :

Generating files
updating cache ./config.cache
creating ./config.status
creating php4.spec
creating main/build-defs.h
creating scripts/phpize
creating scripts/man1/phpize.1
creating scripts/php-config
creating scripts/man1/php-config.1
creating sapi/cli/php.1
creating main/php_config.h
creating main/internal_functions.c
creating main/internal_functions_cli.c
+--------------------------------------------------------------------+
| License:                                                           |
| This software is subject to the PHP License, available in this     |
| distribution in the file LICENSE.  By continuing this installation |
| process, you are bound by the terms of this license agreement.     |
| If you do not agree with the terms of this license, you must abort |
| the installation process at this point.                            |
+--------------------------------------------------------------------+
|                          *** NOTE ***                              |
|            The default for register_globals is now OFF!            |
|                                                                    |
| If your application relies on register_globals being ON, you       |
| should explicitly set it to on in your php.ini file.               |
| Note that you are strongly encouraged to read                      |
| http://www.php.net/manual/en/security.globals.php                  |
| about the implications of having register_globals set to on, and   |
| avoid using it if possible.                                        |
+--------------------------------------------------------------------+

Thank you for using PHP.

After configuring PHP we have to build it, of course.

# make -j3
main/internal_functions_cli.lo -lcrypt -lcrypt -lpq -lmysqlclient -lmhash -lmcrypt -lltdl 
-lfreetype -lpng -lz -lz -lssl -lcrypto -lresolv -lm -ldl -lnsl -lcrypt -lcrypt  
-o sapi/cli/php /usr/lib/gcc-lib/i686-pc-linux-gnu/3.3.5-20050130/../../../../i686-pc-linux-
gnu/bin/ld: warning: creating a DT_TEXTREL in object.

Build complete.
(It is safe to ignore warnings about tempnam and tmpnam).

As the build says, it really is safe to ignore warnings about tempnam and tmpnam. The next step obviously would be to install the PHP package but we'd like to run some tests first :

 # make test
=====================================================================
TIME END 2005-10-28 14:20:27
=====================================================================
TEST RESULT SUMMARY
---------------------------------------------------------------------
Exts skipped    :   65
Exts tested     :   23
---------------------------------------------------------------------
Number of tests :  630
Tests skipped   :  242 (38.4%)
Tests warned    :    0 (0.0%)
Tests failed    :    0 (0.0%)
Tests passed    :  388 (60.8%)
---------------------------------------------------------------------
Time taken      :   30 seconds
=====================================================================

Please allow this report to be sent to the PHP QA
team. This will give us a better understanding in how
PHP's test cases are doing.  Note that the report will include
detailed configuration data about your system
so if you are worried about exposing sensitive data,
save this to a file first and remove any sensitive data
and then send this file to php-qa@lists.php.net.
(choose "s" to just save the results to a file)? [Yns]: n

Now we can install the build and tested package. The modules will be installed into /usr/local/apache/1.3.34/libexec and the CLI binary will be installed into /usr/local/bin This step causes no version conflicts when you update an existing configuration.

# make install
Installing PHP SAPI module:       apache
[activating module `php4' in /usr/local/apache/1.3.34/conf/httpd.conf]
cp libs/libphp4.so /usr/local/apache/1.3.34/libexec/libphp4.so
chmod 755 /usr/local/apache/1.3.34/libexec/libphp4.so
cp /usr/local/apache/1.3.34/conf/httpd.conf /usr/local/apache/1.3.34/conf/httpd.conf.bak
cp /usr/local/apache/1.3.34/conf/httpd.conf.new /usr/local/apache/1.3.34/conf/httpd.conf
rm /usr/local/apache/1.3.34/conf/httpd.conf.new
Installing PHP CLI binary:        /usr/local/bin/
Installing PHP CLI man page:      /usr/local/man/man1/
Installing PEAR environment:      /usr/local/lib/php/
[PEAR] Archive_Tar    - already installed: 1.1
[PEAR] Console_Getopt - already installed: 1.2
[PEAR] PEAR           - already installed: 1.3.5
Wrote PEAR system config file at: /usr/local/etc/pear.conf
You may want to add: /usr/local/lib/php to your php.ini include_path
[PEAR] HTML_Template_IT- already installed: 1.1
[PEAR] Net_UserAgent_Detect- already installed: 2.0.1
[PEAR] XML_RPC        - already installed: 1.3.1
Installing build environment:     /usr/local/lib/php/build/
Installing header files:          /usr/local/include/php/
Installing helper programs:       /usr/local/bin/
  program: phpize
  program: php-config
Installing man pages:             /usr/local/man/man1/
  page: phpize.1
  page: php-config.1

The next steps only apply to you if you install a new server. If you update Apache, PHP or some modules you don't want to screw up your existing configuration.

# cp php.ini-recomended /etc/php.ini

8.3 Install Zend Optimizer

# cd /usr/local/src/ZendOptimizer-2.5.10a-linux-glibc21-i386
# ./install.sh

Follow the on screen instructions

8.4 Building ModSecurity via APXS

To build ModSecurity we first change into its source directory ...

# cd /usr/local/src/modsecurity-1.9.5

Then we are going to build the module via apxs of our freshly built Apache 1.3.39 ...

# /usr/local/apache/1.3.39/bin/apxs -cia apache1/mod_security.c

This should create the following output :

gcc -DLINUX=22 -DHAVE_SET_DUMPABLE -I/usr/include/db1 -DMOD_SSL=208125 -DUSE_HSREGEX -DEAPI
-march=pentium3 -mcpu=pentium3 -O3 -pipe -fomit-frame-pointer -fpic -DSHARED_MODULE 
-I/usr/local/apache/1.3.39/include  -c apache1/mod_security.c
gcc -shared -o apache1/mod_security.so mod_security.o
[activating module `security' in /usr/local/apache/1.3.39/conf/httpd.conf]
cp apache1/mod_security.so /usr/local/apache/1.3.39/libexec/mod_security.so
chmod 755 /usr/local/apache/1.3.39/libexec/mod_security.so
cp /usr/local/apache/1.3.39/conf/httpd.conf /usr/local/apache/1.3.39/conf/httpd.conf.bak
cp /usr/local/apache/1.3.39/conf/httpd.conf.new /usr/local/apache/1.3.39/conf/httpd.conf
rm /usr/local/apache/1.3.39/conf/httpd.conf.new

8.5 Building ModGZip via APXS

ModGZip is an Apache module which is built via Apache's APXS. ModGZip comes with a Makefile
which is best left untouched. To build it we change into its source directory ...

# cd /usr/local/src/mod_gzip-1.3.26.1a

and then type :

# make APXS=/usr/local/apache/1.3.39/bin/apxs

When you see something like this your build procedure should be completed :

/usr/local/apache/1.3.39/bin/apxs -Wc,-Wall,-O3,-fomit-frame-pointer,-pipe -c mod_gzip.c 
mod_gzip_debug.c mod_gzip_compress.c -o mod_gzip.so
gcc -DLINUX=22 -DHAVE_SET_DUMPABLE -I/usr/include/db1 -DMOD_SSL=208125 -DUSE_HSREGEX -DEAPI 
-march=pentium3 -mcpu=pentium3 -O3 -pipe -fomit-frame-pointer -fpic -DSHARED_MODULE 
-I/usr/local/apache/1.3.39/include -Wall,-O3,-fomit-frame-pointer,-pipe  -c mod_gzip.c
gcc -DLINUX=22 -DHAVE_SET_DUMPABLE -I/usr/include/db1 -DMOD_SSL=208125 -DUSE_HSREGEX -DEAPI 
-march=pentium3 -mcpu=pentium3 -O3 -pipe -fomit-frame-pointer -fpic -DSHARED_MODULE 
-I/usr/local/apache/1.3.39/include -Wall,-O3,-fomit-frame-pointer,-pipe  -c mod_gzip_debug.c
gcc -DLINUX=22 -DHAVE_SET_DUMPABLE -I/usr/include/db1 -DMOD_SSL=208125 -DUSE_HSREGEX -DEAPI 
-march=pentium3 -mcpu=pentium3 -O3 -pipe -fomit-frame-pointer -fpic -DSHARED_MODULE 
-I/usr/local/apache/1.3.39/include -Wall,-O3,-fomit-frame-pointer,-pipe  -c mod_gzip_compress.c
gcc -shared -o mod_gzip.so mod_gzip_compress.o mod_gzip_debug.o mod_gzip.o -o mod_gzip.so 
-Wc,-Wall,-O3,-fomit-frame-pointer,-pipe
# make install APXS=/usr/local/apache/1.3.39/bin/apxs
/usr/local/apache/1.3.39/bin/apxs -A -i mod_gzip.so
[preparing module `gzip' in /usr/local/apache/1.3.39/conf/httpd.conf]
cp mod_gzip.so /usr/local/apache/1.3.39/libexec/mod_gzip.so
chmod 755 /usr/local/apache/1.3.39/libexec/mod_gzip.so
cp /usr/local/apache/1.3.39/conf/httpd.conf /usr/local/apache/1.3.39/conf/httpd.conf.bak
cp /usr/local/apache/1.3.39/conf/httpd.conf.new /usr/local/apache/1.3.39/conf/httpd.conf
rm /usr/local/apache/1.3.39/conf/httpd.conf.new

9 Configuration

9.1 httpd.conf

Example global configuration :

ServerType standalone
ServerRoot "/usr/local/apache/current"
PidFile /var/run/httpd.pid
ScoreBoardFile /var/log/apache/httpd.scoreboard
 
Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15
 
MinSpareServers 5
MaxSpareServers 10
StartServers 5
 
MaxClients 150
MaxRequestsPerChild 0
 
################################################################
### load mod_security first otherwise it won't work properly ###
 
LoadModule security_module    libexec/mod_security.so
 
LoadModule vhost_alias_module libexec/mod_vhost_alias.so
LoadModule env_module         libexec/mod_env.so
LoadModule define_module      libexec/mod_define.so
LoadModule config_log_module  libexec/mod_log_config.so
LoadModule mime_magic_module  libexec/mod_mime_magic.so
LoadModule mime_module        libexec/mod_mime.so
LoadModule includes_module    libexec/mod_include.so
LoadModule dir_module         libexec/mod_dir.so
LoadModule cgi_module         libexec/mod_cgi.so
LoadModule action_module      libexec/mod_actions.so
LoadModule alias_module       libexec/mod_alias.so
LoadModule rewrite_module     libexec/mod_rewrite.so
LoadModule access_module      libexec/mod_access.so
LoadModule auth_module        libexec/mod_auth.so
LoadModule anon_auth_module   libexec/mod_auth_anon.so
LoadModule digest_module      libexec/mod_digest.so
LoadModule proxy_module       libexec/libproxy.so
LoadModule cern_meta_module   libexec/mod_cern_meta.so
LoadModule expires_module     libexec/mod_expires.so
LoadModule headers_module     libexec/mod_headers.so
LoadModule usertrack_module   libexec/mod_usertrack.so
LoadModule log_forensic_module libexec/mod_log_forensic.so
LoadModule unique_id_module   libexec/mod_unique_id.so
LoadModule setenvif_module    libexec/mod_setenvif.so
 
LoadModule php4_module        libexec/libphp4.so
 
LoadModule gzip_module        libexec/mod_gzip.so
 
<IfDefine SSL>
LoadModule ssl_module         libexec/libssl.so
</IfDefine>
 
 
ClearModuleList
AddModule mod_security.c
 
AddModule mod_vhost_alias.c
AddModule mod_env.c
AddModule mod_define.c
AddModule mod_log_config.c
AddModule mod_mime_magic.c
AddModule mod_mime.c
AddModule mod_include.c
AddModule mod_dir.c
AddModule mod_cgi.c
AddModule mod_actions.c
AddModule mod_alias.c
AddModule mod_rewrite.c
AddModule mod_access.c
AddModule mod_auth.c
AddModule mod_auth_anon.c
AddModule mod_digest.c
AddModule mod_proxy.c
AddModule mod_cern_meta.c
AddModule mod_expires.c
AddModule mod_headers.c
AddModule mod_usertrack.c
AddModule mod_log_forensic.c
AddModule mod_unique_id.c
AddModule mod_so.c
AddModule mod_setenvif.c
 
AddModule mod_php4.c
 
AddModule mod_gzip.c
 
<IfDefine SSL>
AddModule mod_ssl.c
</IfDefine>

9.1.1 global ModSecurity configuration

################################################################
### global mod_security configuration ##########################
 
<IfModule mod_security.c>
# Turn the filtering engine On or Off
SecFilterEngine On
 
Include /etc/mod_sec.conf
 
# set chroot path
SecChrootDir /www
 
# Make sure that URL encoding is valid
SecFilterCheckURLEncoding On
 
# Unicode encoding check
SecFilterCheckUnicodeEncoding On
 
# Only allow bytes from this range
SecFilterForceByteRange 1 255
 
# Only log suspicious requests
SecAuditEngine RelevantOnly
 
# The name of the audit log file
SecAuditLog /var/log/apache/modsec_audit_log
 
# Debug level set to a minimum
SecFilterDebugLog /var/log/apache/modsec_debug_log
SecFilterDebugLevel 0
 
# Should mod_security inspect POST payloads
 
SecFilterScanPOST On
 
# By default log and deny suspicious requests with HTTP status 406
 
SecFilterDefaultAction "deny,log,status:406"
 
</IfModule>

9.1.2 Global ModGZip configuration

################################################################
### global mod_gzip configuration ##############################
 
 
<IfModule mod_gzip.c>
 
mod_gzip_on yes
mod_gzip_dechunk yes
mod_gzip_keep_workfiles No
mod_gzip_temp_dir /tmp
mod_gzip_minimum_file_size  500
mod_gzip_maximum_file_size  5000000
mod_gzip_maximum_inmem_size 1000000
mod_gzip_add_header_count     Yes
 
mod_gzip_min_http             1001
 
mod_gzip_item_include file \.htm$
mod_gzip_item_include file \.html$
mod_gzip_item_include mime ^text/html
mod_gzip_item_include mime ^text/plain
 
mod_gzip_item_include file \.php$
mod_gzip_item_include handler x-httpd-php
mod_gzip_item_include mime ^application/x-httpd-php$
mod_gzip_item_include mime httpd/unix-directory
 
mod_gzip_item_exclude file "\.css$"
mod_gzip_item_exclude file "\.js$"
 
# %h %l %u %t \"%V %r\" %<s %b mod_gzip:
 
LogFormat "%h \"%V %r\" - %{mod_gzip_result}n In:%{mod_gzip_input_size}n 
- Out:%{mod_gzip_output_size}n = %{mod_gzip_compression_ratio}n Prozent." mod_gzip_info2
 
CustomLog /var/log/apache/mod_gzip.log mod_gzip_info2
 
</IfModule>

Example Reverse Proxy Container :

### test.radion.org #######################################################################
 
<VirtualHost *:80>
 
    ServerAdmin youremail@yourdomain.com
    ServerName  yourhost.yourdomain.org
    ServerAlias yourhost.anotherdomain.org www.yourdomain.com
 
    LogLevel    warn
    ErrorLog    /var/log/apache/container/host.yourdomain.org/error_log
    CustomLog   /var/log/apache/container/host.yourdomain.org/access_log combined env=!dontlog
    CustomLog   /var/log/apache/container/host.yourdomain.org/clickstream "%h %t %{cookie}n %r %t"
 
    ProxyPass           /       http://your.internal.appserver.com/
    ProxyPassReverse    /       http://your.internal.appserver.com/
 
</VirtualHost>

9.2 tweaking the system to use SSL in JailRoot

The JailRoot where all Apache children are confined brings a major dilemma when it comes to SSL. Obviously the parent process and the children involved in SSL communication have to share the same SSL mutex. If your httpd.conf is properly configured you find the following section :

Check that the variables SSLSessionCache and SSLMutex are pointing to /var/cache/apache/ssl/ as described in the httpd.conf section above.

<IfModule mod_ssl.c>
 
SSLPassPhraseDialog  builtin
 
SSLSessionCache         dbm:/var/cache/apache/ssl/ssl_scache
SSLSessionCacheTimeout  300
 
SSLMutex  file:/var/cache/apache/ssl/ssl_mutex
 
SSLRandomSeed startup file:/dev/urandom 512
SSLRandomSeed connect file:/dev/urandom 512
 
SSLLog      /var/log/apache/ssl_engine_log
SSLLogLevel warn
 
</IfModule>

Now you should create the directory /www/var/apache/ssl

# mkdir /www/var/
# mkdir /www/var/apache
# mkdir /www/var/apache/ssl

We have to link back this directory to the real /var/ so that the parent process see's exactly the same path with exactly the same files :

# ln -s /www/var/cache/apache/ /var/cache

Your /var/cache directory should look like similiar to this :

# ls -al /var/cache
total 16
drwxr-xr-x   4 root   root    4096 Sep 10 08:34 .
drwxr-xr-x  13 root   root    4096 Oct  5 18:57 ..
lrwxrwxrwx   1 wwwrun wwwrun    22 Oct  9 17:30 apache -> /www/var/cache/apache/
drwxrwxr-x   3 root   portage 4096 Oct 10 15:02 edb
drwxrwxr-x  19 root   man     4096 Sep  6 00:09 man

Both /var/cache/apache/ssl/ and /www/var/cache/apache/ssl/ should now contain the same content :

# ls -al /www/var/cache/apache/ssl

total 16
drwxr-xr-x  2 wwwrun wwwrun 4096 Oct 29 12:44 .
drwxr-xr-x  3 wwwrun wwwrun 4096 Sep 10 08:33 ..
-rw-------  1 wwwrun root      0 Oct 29 12:44 ssl_mutex.11801
-rw-------  1 wwwrun root      0 Sep 10 23:13 ssl_mutex.19929
-rw-------  1 wwwrun root      0 Oct  7 21:56 ssl_mutex.26688
-rw-------  1 wwwrun root      0 Oct 29 12:44 ssl_scache.dir
-rw-------  1 wwwrun root   8192 Oct 29 23:20 ssl_scache.pag
# ls -al /var/cache/apache/ssl/

total 16
drwxr-xr-x  2 wwwrun wwwrun 4096 Oct 29 12:44 .
drwxr-xr-x  3 wwwrun wwwrun 4096 Sep 10 08:33 ..
-rw-------  1 wwwrun root      0 Oct 29 12:44 ssl_mutex.11801
-rw-------  1 wwwrun root      0 Sep 10 23:13 ssl_mutex.19929
-rw-------  1 wwwrun root      0 Oct  7 21:56 ssl_mutex.26688
-rw-------  1 wwwrun root      0 Oct 29 12:44 ssl_scache.dir
-rw-------  1 wwwrun root   8192 Oct 29 23:24 ssl_scache.pag

9.3 /etc/init.d/apache script

Here is a modified gentoo apache start/stop script to be placed into /etc/init.d/

#!/sbin/runscript
# Copyright 1999-2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/net-www/apache/files/apache.rc6,v 1.20 2004/07/15 00:24:42 agriffis Exp $
 
opts="${opts} reload configcheck"
 
depend() {
        need net
        use dns logger netmount
        before sshd
}
 
start() {
        ebegin "Starting Apache HTTP Server"
        env -i PATH=$PATH PERL5LIB=PERL5LIB /sbin/start-stop-daemon -o --quiet \
                --start --startas /usr/local/apache/current/bin/httpd \
                --pidfile /var/run/httpd.pid -- ${APACHE_OPTS}
        eend $?
}
 
stop() {
        ebegin "Pre-Checking httpd.conf"
        /usr/local/apache/current/bin/httpd -T ${APACHE_OPTS} &> /dev/null
 
        if [ "$?" = "0" ]
          then
 
          einfo "Shutting down Apache HTTP Server"
          #/usr/local/apache/current/bin/apachectl stop >/dev/null
          start-stop-daemon -o --quiet --stop --pidfile /var/run/httpd.pid
          eend $?
        else
          einfo "Errors in httpd.conf - SHUTDOWN aborted"
          eend 128
        fi
}
 
configcheck() {
        ebegin "Re-Check httpd.conf"
        /usr/local/apache/current/bin/httpd -T ${APACHE_OPTS}
        eend $?
}
 
 
reload() {
        ebegin "Gracefully restarting apache"
        /usr/local/apache/current/bin/httpd -t ${APACHE_OPTS} &>/dev/null
        if [ "$?" = "0" ]
        then
                if [ -f /var/run/httpd.pid ]
                then
                        kill -USR1 $(</var/run/httpd.pid)
                        eend $?
                else
                        svc_start
                        eend $?
                fi
        else
                if [ -f /var/run/httpd.pid ]
                then
                        svc_stop
                fi
                #show the error(s)
                /usr/local/apache/current/bin/httpd -t ${APACHE_OPTS}
                eend 1
        fi
}

Until now I did not find any way to restart Apache gracefully. If you send a kill -USR1 to httpd manually Apache will simply die but not start again. If someone else has this problem or even has found a solution for that particular problem, don't hesitate to change it directly here in the wiki or send us an email.

Also, if you can contribute working init scripts for other UNIXes / Linuxes we would gladly appreciate them.

10 Activate apache


# ln -sf /usr/local/apache/1.3.34 /usr/local/apache/current
# ls -al /usr/local/apache

total 16
drwxr-xr-x   4 root root 4096 Sep 12 10:17 .
drwxr-xr-x  13 root root 4096 Sep 10 18:25 ..
drwxr-xr-x   9 root root 4096 Sep 12 10:17 1.3.34
lrwxrwxrwx   1 root root    7 Sep 10 18:08 current -> 1.3.34/

11 Testing

11.1 General function

 
top - 23:31:29 up 20 days,  4:38,  4 users,  load average: 0.01, 0.02, 0.00
Tasks:  50 total,   1 running,  49 sleeping,   0 stopped,   0 zombie
Cpu0  :  0.0% us,  0.0% sy,  0.0% ni, 100.0% id,  0.0% wa,  0.0% hi,  0.0% si
Cpu1  :  0.0% us,  0.0% sy,  0.0% ni, 100.0% id,  0.0% wa,  0.0% hi,  0.0% si
Mem:   1556012k total,   884264k used,   671748k free,   211920k buffers
Swap:  1004052k total,        0k used,  1004052k free,   336840k cached
 
  PID  PPID    TIME+  P %CPU %MEM  PR  NI S  VIRT SWAP  RES  SHR  UID COMMAND
13832 11440   0:00.18 1  0.3  0.1  16   0 R  1860  916  944  748    0 top
12019 11802   0:35.60 0  0.0  1.2  16   0 S 21612 3656  17m 3560  666 /usr/local/apache/current/bin/httpd -D SSL
11838 11802   0:35.50 1  0.0  1.1  16   0 S 21496 3660  17m 3556  666 /usr/local/apache/current/bin/httpd -D SSL
11811 11802   0:45.61 0  0.0  1.2  16   0 S 21552 3624  17m 3592  666 /usr/local/apache/current/bin/httpd -D SSL
11810 11802   0:32.76 0  0.0  1.2  16   0 S 21572 3576  17m 3640  666 /usr/local/apache/current/bin/httpd -D SSL
11809 11802   0:47.12 0  0.0  1.1  16   0 S 21452 3560  17m 3656  666 /usr/local/apache/current/bin/httpd -D SSL
11807 11802   0:38.64 1  0.0  1.3  16   0 S 24424 3660  20m 3560  666 /usr/local/apache/current/bin/httpd -D SSL
11806 11802   0:40.73 0  0.0  1.4  16   0 S 24908 3660  20m 3564  666 /usr/local/apache/current/bin/httpd -D SSL
11805 11802   0:33.50 0  0.0  1.1  16   0 S 21228 3640  17m 3572  666 /usr/local/apache/current/bin/httpd -D SSL
11804 11802   0:41.47 1  0.0  1.3  16   0 S 24316 3640  20m 3576  666 /usr/local/apache/current/bin/httpd -D SSL
11803 11802   0:45.92 0  0.0  3.4  16   0 S 69668  16m  51m 3644  666 /usr/local/apache/current/bin/httpd -D SSL
11802     1   0:00.18 1  0.0  0.5  16   0 S 11928 4304 7624 2968    0 /usr/local/apache/current/bin/httpd -D SSL
 5874     1   0:00.00 0  0.0  0.0  16   0 S  1504  884  620  540    0 /sbin/agetty 38400 tty1 linux
 5804     1   0:00.00 1  0.0  0.0  16   0 S  1500  880  620  540    0 /sbin/agetty 38400 tty3 linux
 5803     1   0:00.00 0  0.0  0.0  16   0 S  1504  884  620  540    0 /sbin/agetty 38400 tty2 linux
 5775     1   0:08.27 0  0.0  0.1  16   0 S  3412 1876 1536 1260    0 /usr/sbin/sshd
 4758     1   0:02.80 0  0.0  0.0  15   0 S  1716  984  732  564    0 /usr/sbin/syslog-ng
 3970     1   0:02.63 0  0.0  0.0  15   0 S     0    0    0    0    0 [kjournald]
 3552     1   0:00.43 1  0.0  0.0  16   0 S  1716  988  728  616    0 /usr/sbin/cron
  766     1   0:00.08 1  0.0  0.0  12  -4 S  1472  984  488  416    0 udevd
  711     1   0:00.79 0  0.0  0.0  15   0 S     0    0    0    0    0 [kjournald]
  710     1   0:00.00 1  0.0  0.0  15   0 S     0    0    0    0    0 [kirqd]
  653     1   0:00.18 0  0.0  0.0  15   0 S     0    0    0    0    0 [kseriod]
   64     9   0:00.00 1  0.0  0.0  19  -5 S     0    0    0    0    0 [aio/1]
   63     9   0:00.00 0  0.0  0.0  19  -5 S     0    0    0    0    0 [aio/0]
   62     1   0:00.00 0  0.0  0.0  25   0 S     0    0    0    0    0 [kswapd0]
   61     9   0:00.42 0  0.0  0.0  15   0 S     0    0    0    0    0 [pdflush]
   60     9   0:00.00 1  0.0  0.0  20   0 S     0    0    0    0    0 [pdflush]
   14     9   0:00.00 1  0.0  0.0  10  -5 S     0    0    0    0    0 [kblockd/1]
   13     9   0:00.26 0  0.0  0.0  10  -5 S     0    0    0    0    0 [kblockd/0]
   12     1   0:00.52 0  0.0  0.0   6 -10 S     0    0    0    0    0 [vesafb]
    9     1   0:00.00 1  0.0  0.0  18  -5 S     0    0    0    0    0 [kthread]
    8     1   0:00.59 1  0.0  0.0  10  -5 S     0    0    0    0    0 [khelper]
    7     1   0:00.00 1  0.0  0.0  10  -5 S     0    0    0    0    0 [events/1]
    6     1   0:00.07 0  0.0  0.0  10  -5 S     0    0    0    0    0 [events/0]
    5     1   0:00.00 1  0.0  0.0  34  19 S     0    0    0    0    0 [ksoftirqd/1]
    4     1   0:00.41 1  0.0  0.0  RT   0 S     0    0    0    0    0 [migration/1]
    3     1   0:00.00 0  0.0  0.0  34  19 S     0    0    0    0    0 [ksoftirqd/0]
    2     1   0:00.31 0  0.0  0.0  RT   0 S     0    0    0    0    0 [migration/0]
    1     0   0:02.68 1  0.0  0.0  16   0 S  1464  960  504  440    0 init [3]


# netstat -patune | grep httpd

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      0          423856     11802/httpd
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      0          423855     11802/httpd

11.2 PHP


11.3 ModSSL


11.4 ModSecurity

11.5 ModGZip

[http://leknor.com/code/gziped.php http://leknor.com/code/gziped.php}

12 Pitfalls & Caveats

Due to ModSecurity's chroot design there are some pitfalls to be aware of :

 Module Order:  ModSecurity requires a specific Apache module execution order to run properly with all modules you
want to include into Apache. Don't mess with ModSecurity's position in the module execution order.


 Hint:  The parent Apache process needs an ssl-mutex and so does the jailrooted child if handling SSL requests
therefore both need to read & write to the same mutex file. To not to make this a jailroot violation you'll have to link it from /www/var/ to /var


 Hint:  PHP, SSL and some Apache modules ( or even your own code ) will need /tmp to work properly but
after chrooting Apache has only access to files and directories below /www so we need a separate
/www/tmp directory there.


 Hint:  If you use ModProxy or any other code which needs /etc/hosts to resolve hostnames be aware of the
fact that /etc cannot be seen from inside the jailroot. You can link /www/etc/hosts to /etc/hosts but I
recommend to create the directory /www/etc and put your own hosts file in there. This way you can even
control the behaviour of ModProxy or your own code differently from what your machine itself would do.


 Hint:  ModSSL behaves even worse because it needs access to some files IN and OUTside of the jailroot and
both path's have to be the same. If Apache refuses to start or missbehaves - have a thorough look into
your error_log files. .


 Hint:  Apache graceful restarting DOES NOT WORK anymore. Once chrooted, Apache cannot access anything located above ChrootDir. For that reason restarting Apache with 'apachectl reload', 'apachectl graceful' or 'kill -HUP apache_pid' will not work as expected. Apache will not be able to read its config file, open logs or load modules once chrooted.


 Shared libraries:  Shared libraries are libraries which are linked to a program at run-time. Nowadays, most programs require some shared libraries to run - libc.so is most common. You can see a list of shared libraries a program requires by running ldd /path/to/program. Loading of these libraries is done automagically by ld.so at startup. mod_chroot doesn't interfere with this mechanism.

A program may also explicitly load a shared library by calling dlopen() and dlsym(). This might cause troubles in a chrooted environment - after a process is chrooted, libraries (usually stored in /lib) might be no longer accessible. This doesn't happen very often, but if it does - there is a solution: you can preload these libraries before chrooting. Apache has a handy directive for that: LoadFile. This is what people reported on the mailing list:

DNS lookups - GNU libc tries to load libnss_dns.so.2 when a first DNS lookup is done. Solution: LoadFile /lib/libnss_dns.so.2Apache 2.0 with mpm_worker on Linux 2.6 - GNU libc tries to load libgcc_s.so.1 when pthread_cancel is called. Solution: LoadFile /lib/libgcc_s.so.1

RADION OpenLAB