Apache MPM ITK RPM for CentOS 5

What is Apache MPM ITK?

Apache2-mpm-itk provides a modified httpd daemon that allows each web site (vhost) in a shared hosting environment to run under a separate user account.

Why is this important?

By default, without a solution like mpm-itk, all web sites run under the "apache" user account. If all web sites are managed by the same entity, this is not necessarily a big issue. If however the content fo these sites is managed by more than one entity, or if one of those sites is hacked, there are serious security implications.

In order for the apache daemon (httpd) to be able to serve-up content and execute the PHP for all of the web sites it hosts, all files must be readable by the "apache" user. This includes things like .htpasswd files and PHP configuration files containing database logins and passwords. Otherwise how could passwords be verified, or how would the PHP interpreter know your MySQL password?

The downside of this in a shared (multi-tenant) hosting environment is that any user hosting a web site on such a server can potentially ask the server to disclose content, password files, configuration files and code for any other web site on that server. Features within PHP designed to mitigate these problems, such as Safe Mode are next to useless, and can provide a false sense of security. These features are trivial to bypass. Consequently Safe Mode itself has been removed from PHP 5.4 and above.

How does it mpm-itk work?

Anyone familiar with how a traditional Unix SMTP MTA delivers mail to local users will be familiar with the basic mechanics of mpm-itk. Instead of running as the "apache" user, httpd runs as root, but with limited privileges. It retains root's ability to "su" to any other user account.  After first determining which web site the request is for, httpd then su's to either a designated user account for that site, or failing that to the regular apache user. By using a different user account per site, it is then possible for each web site owner (or more likely the servers sysadmin) to protect their content by ensuring it is only readable by either the site owner, or the http process running under the user account designated in the apache vhost configuration.

See here for more information: http://mpm-itk.sesse.net/

The Spec File

The spec file can be downloaded from here. For those more security conscious, this is a patch against the current (2.2.3-65) httpd.spec, complete with explanation:

--- httpd-orig.spec	2012-11-12 13:42:00.000000000 +0000
+++ httpd.spec	2012-12-27 16:23:17.000000000 +0000
@@ -147,6 +147,18 @@
 Patch200: httpd-2.2.3-proxy229.patch
 Patch201: httpd-2.2.3-cache229.patch
 Patch202: httpd-2.2.3-deflate2215.patch
+# ITK
+Patch402: http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.17-01/02-rename-prefork-to-itk.patch
+Patch403: http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.17-01/03-add-mpm-to-build-system.patch
+Patch404: http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.17-01/04-correct-output-makefile-location.patch
+Patch405: http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.17-01/05-add-copyright.patch
+Patch406: http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.17-01/06-hook-just-after-merging-perdir-config.patch
+Patch407: http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.17-01/07-base-functionality.patch
+Patch408: http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.17-01/08-max-clients-per-vhost.patch
+Patch409: http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.17-01/09-capabilities.patch
+Patch410: http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.17-01/10-nice.patch
+Patch411: http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.17-01/11-fix-htaccess-reads-for-persistent-connections.patch
 License: Apache Software License
 Group: System Environment/Daemons
@@ -195,6 +207,22 @@
 reference guide for the Apache HTTP server. The information can
 also be found at http://httpd.apache.org/docs/2.2/.
+%package -n httpd-itk
+Group: System Environment/Daemons
+Summary: MPM Itk for Apache HTTP Server
+URL:                    http://mpm-itk.sesse.net/
+License:                ASL 2.0
+Requires: httpd = %{version}-%{release}
+%description -n httpd-itk
+This package contain mpm-itk which is an MPM (Multi-Processing Module) for the
+Apache web server. Mpm-itk allows you to run each of your vhost under a separate
+uid and gid — in short, the scripts and configuration files for one vhost no
+longer have to be readable for all the other vhosts.
+In summary it is Apache module (opposite CGI solutions like suexec), fast and
+allow safely use non-thread-aware code software (like many PHP extensions f.e.)
 %package -n mod_ssl
 Group: System Environment/Daemons
 Summary: SSL/TLS module for the Apache HTTP server
@@ -355,6 +383,21 @@
 %patch35 -p1 -b .connectiontimeout
 %patch38 -p1 -b .change-state
+mkdir server/mpm/experimental/itk/
+cp server/mpm/prefork/* server/mpm/experimental/itk/
+mv server/mpm/experimental/itk/prefork.c server/mpm/experimental/itk/itk.c
+%patch402 -p1
+%patch403 -p1
+%patch404 -p1
+%patch405 -p1
+%patch406 -p1
+%patch407 -p1
+%patch408 -p1
+%patch409 -p1
+%patch410 -p1
+%patch411 -p1
 # Patch in vendor/release string
 sed "s/@VENDOR@/%{vstring}/;s/@RELEASE@/%{release}/" < %{PATCH20} | patch -p1 -b -z .release
@@ -444,6 +487,7 @@
         --enable-authn-anon --enable-authn-alias
 # For the other MPMs, just build httpd and no optional modules
+mpmbuild itk --enable-modules=none
 mpmbuild worker --enable-modules=none
 mpmbuild event --enable-modules=none
@@ -461,6 +505,7 @@
 # install alternative MPMs
 install -m 755 worker/httpd $RPM_BUILD_ROOT%{_sbindir}/httpd.worker
 install -m 755 event/httpd $RPM_BUILD_ROOT%{_sbindir}/httpd.event
+install -m 755 itk/httpd $RPM_BUILD_ROOT%{_sbindir}/httpd.itk
 # install conf file/directory
 mkdir $RPM_BUILD_ROOT%{_sysconfdir}/httpd/conf.d
@@ -639,7 +684,7 @@
 # Verify that the same modules were built into the httpd binaries
 ./prefork/httpd -l | grep -v prefork > prefork.mods
-for mpm in worker; do
+for mpm in worker itk; do
   ./${mpm}/httpd -l | grep -v ${mpm} > ${mpm}.mods
   if ! diff -u prefork.mods ${mpm}.mods; then
     : Different modules built into httpd binaries, will not proceed
@@ -676,6 +721,7 @@
+%exclude %{_sbindir}/httpd.itk
 %attr(4510,root,%{suexec_caller}) %{_sbindir}/suexec
@@ -709,6 +755,10 @@
 %config %{_sysconfdir}/httpd/conf.d/manual.conf
+%files -n httpd-itk
 %files -n mod_ssl


The patches are straight from the mpm-itk web site linked to above. However, we have not used either the monolitic patch, or the 01-copy-prefork.patch file. This is because both of those files contain source code lifted straight from Apache 2.2.17. Specifically that "01" patch simply deposits 2.2.17 prefork daemon code to an new folder named "server/mpm/experimental/itk/". This means that if any security flaws do arise in the prefork daemon, patches provided by Redhat to address this would not be applied to the ITK daemon, as it would continue to contain only code from 2.2.17.
Instead our spec file first applies all of RedHat's back-ported security fixes (as normal), and then copies that fully security-patched prefork code over to a fresh "itk" folder like so:
mkdir server/mpm/experimental/itk/
These three commands are the equivalent of applying the "01" patch, but this approach ensures that any future security patches applied to the prefork daemon will also be applied to the itk daemon.

The Source RPM

The full source RPM file is available here. Building the RPM is pretty straightforward:
# rpm -ivh httpd-2.2.3-65.el5.centos.3.src.rpm
# rpmbuild -bb /usr/src/redhat/SPECS/httpd.spec
# cd /usr/src/redhat/RPMS/`uname -i`/
# rpm -ivh httpd-itk-2.2.3-65.el5.centos.3.`uname -i`.rpm
If you have any problems with the "el5.centos" dist name being missing from your RPM, check that %dist is defined in your /etc/rpm/macros.disttag file. Like so:
%rhel 5
%dist .el5.centos
%el5 1


To actually enable htpd.itk for your sites, edit /etc/sysconfig/httpd, and add a line like so:

PHP Considerations

If you are using mod_php, you need to make a change to /etc/httpd/conf.d/php.conf. Specifially you need to ensure that the ITK daemon is treated on the same way as the prefork daemon. The beginning of your php.conf should look something like this:
<IfModule !worker.c>
  LoadModule php5_module modules/libphp5.so
<IfModule worker.c>
  # Use of the "ZTS" build with worker is experimental, and no shared
  # modules are supported.
  LoadModule php5_module modules/libphp5-zts.so