The Apache Software Foundation HTTP Server Project (commonly known as Apache) is the dominant Web server on the Internet today, which accounts for more than 60% of the market share. The Apache server is part of an increasingly popular LAMP software configuration. LAMP is a free software program, a WEB platform built on open source technologies such as Linux, Apache, MySQL, and PHP. In this article, you will learn a way to improve LAMP security using the Mod_proxy module and multiple back-end servers. I'll discuss the pros and cons of this approach and provide a sample configuration.
PHP and Apache: Security challenges
A challenge for LAMP administrators is to provide all the features of a complete PHP system while ensuring a secure environment for all users of the system. Using PHP's Safe mode is a technique to achieve this, but it also restricts users too much, and some PHP applications do not work after the facility is enabled.
The root of the PHP security problem is the way most Apache servers are configured. Because most Apache configurations run under a special Www-data user ID, all users hosting the Web site must make sure that the user can read their files by default. Therefore, all other users on the system may have access to all of the web-accessible files of a user, so a security vulnerability that is otherwise unrelated to your system can be a breach of your Web site. This is even more serious if the file or directory must be set to Www-data user-writable.
By using CGI programs, such as programs written in popular languages such as Perl and Python, you can eliminate some of the effects of this problem when using the suexec mechanism. Simply put, suEXEC uses a special intermediary program to execute a CGI program with the user ID of the program owner. This is a very effective mechanism that has been in use for many years.
However, when using mod_php module host hosting, the PHP page executes as part of the Apache main process. Therefore, they inherit all the credentials of the Apache process, and any work they perform on the file system must be performed as a www-data user.
To run Apache under multiple user IDs
For the problem described above, the obvious solution is to require that all requests to a user domain come from a single Apache instance that owns only the credentials of this user. You can configure Apache to obtain credentials for any user at startup. This approach solves the problem by assigning a simple set of individual Internet-visible IP address/port combinations to each user.
This method is not valid for more complex settings where the IP address is valuable. When a single Apache instance can control a particular IP address/port combination, only the virtual host is used, which is a widely used technique in the Apache system. This eliminates the possibility that multiple domains belonging to multiple users will use the same IP address/port combination.
Apache 2.0 introduces the concept of a multi-processor module (multiprocessing module,mpm). There is an experimental module perchild in the MPM provided by the Basic Apache 2.0 package, which assigns a distributor thread to an IP address/port combination and passes the request to a child thread running under a separate user's credentials, thereby implementing a virtual host under multiple user IDs. Unfortunately, Perchild is still experimental, it does not necessarily work, and was removed from the official Apache release package when Apache 2.2 was released. Prior to this, it was recognized that there was still a need for a stable and perchild-like Mpm,apache community to begin developing many MPM to make up for this shortcoming. METUXMPM and process-oriented peruser are working in this direction.
One solution: Mod_proxy
Although no formal Apache MPM can directly provide a virtual host under multiple user IDs, this behavior can still be implemented in the Apache system through some configuration and management. The core concept of this approach is the use of the Mod_proxy module, which, together with other features, enables Apache to forward page requests to other servers and to pass the response back to the client that originally made the request.
Listing 1. Example of reverse proxy configuration for basic request forwarding
Proxyrequests off
Proxypass/foo Http://foo.example.com/bar
Proxypassreverse/foo Http://foo.example.com/bar
The code in Listing 1 is a simple example that forwards requests for any page under the/foo hierarchy of a host to the corresponding page of Http://foo.example.com/bar. For example, a request to a/foo/index.htm page is forwarded to http://foo.example.com/bar/index.htm. You can use this principle to solve a problem.
Sample Scenario
Let's consider a scenario where the Apache administrator must establish two domains for two separate clients. A customer is an online start-up and is focused on online security. Another is a personal customer, he is more relaxed about site security, may upload unsafe code to this site. Therefore, the Apache administrator must take steps to isolate the two sites.
As a result, administrators have two domains: Www.startup.tld, which belongs to an online startup (user ID startup), and Www.reckless.tld, which belongs to the individual (user ID Nimrod). To solve this problem, the administrator decided to use the Mod_proxy solution. The administrator gives each user a separate Apache instance that runs under the user's own user ID, uses a private IP address/port combination, and uses the Mod_proxy solution to provide access to the two-user domain through a façade server that acts as a www-d ATA run, using a common IP address/port combination. Figure 1 illustrates the entire scenario.
Figure 1. Scenario Example
Recommended Apache Version
For each element in the sample application configuration, the Apache administrator should use the Apache version listed in table 1.
Table 1. Apache version used in the sample application
Element Apache version Reason
Façade server Apache 2, running worker or event MPM Apache 2 has made important improvements to the Mod_proxy module. Worker and event MPM are threaded to help reduce the memory overhead of a façade server.
The back-end server Apache 1.3, or the Apache 2 Apache administrator running Prefork MPM must be aware that the PHP module should not run in an online environment. These two solutions provide a process-based environment for PHP modules.
Configuration of the back-end Apache instance
The code snippet in Listing 2 and listing 3 illustrates the fundamental differences with the standard Apache configuration. You should add them to the appropriate configuration as needed, such as the PHP feature configuration that is ignored here.
Listing 2. Apache configuration of online start-up enterprises
# Stuff every Apache configuration needs
ServerType Standalone
Lockfile/var/lock/apache/accept.startup.lock
Pidfile/var/run/apache.startup.pid
ServerName Necessaryevil.startup.tld
DocumentRoot "/home/startup/web"
# Essential Modules
LoadModule access_module/usr/lib/apache/1.3/mod_access.so
# Which user to run this Apache configuration as
User Startup
Group Startup
# This must is off else the host isn ' t passed correctly
Usecanonicalname off
# The Ip/port combination to listen on
Listen 127.0.0.2:10000
# Using name-based Virtual hosting allows to host multiple sites per Ip/port combo
Namevirtualhost 127.0.0.2:10000
<virtualhost 127.0.0.2:10000>
ServerName Www.startup.tld
# you can add aliases so long as the façade server is aware of them!
Serveralias Startup.tld
DocumentRoot "/home/startup/web/www.startup.tld"
<Directory/home/startup/web/www.startup.tld/>
Options Indexes followsymlinks multiviews execcgi Includes
AllowOverride All
Order Allow,deny
Allow from all
</Directory>
</VirtualHost>
Listing 3. Apache Configuration for individual customers
# Stuff every Apache configuration needs
ServerType Standalone
Lockfile/var/lock/apache/accept.nimrod.lock
Pidfile/var/run/apache.nimrod.pid
ServerName Necessaryevil.nimrod.tld
DocumentRoot "/home/nimrod/web"
# Essential Modules
LoadModule access_module/usr/lib/apache/1.3/mod_access.so
# Which user to run this Apache configuration as
User Nimrod
Group Nimrod
# This must is off else the host isn ' t passed correctly
Usecanonicalname off
# The Ip/port combination to listen on
Listen 127.0.0.2:10001
# Using name-based Virtual hosting allows to host multiple sites per Ip/port combo
Namevirtualhost 127.0.0.2:10001
<virtualhost 127.0.0.2:10001>
ServerName Www.reckless.tld
# you can add aliases so long as the façade server is aware of them!
Serveralias Reckless.tld
DocumentRoot "/home/nimrod/web/www.reckless.tld"
<Directory/home/nimrod/web/www.reckless.tld/>
Options Indexes followsymlinks multiviews execcgi Includes
AllowOverride All
Order Allow,deny
Allow from all
</Directory>
</VirtualHost>
Listing 4 illustrates the configuration of the façade Apache instance.
Listing 4. The Apache configuration of the façade Apache instance
# Stuff every Apache configuration needs
Lockfile/var/lock/apache/accept.www-data.lock
Pidfile/var/run/apache.www-data.pid
ServerName Necessaryevil.facade.server
DocumentRoot "/home/www-data"
# Essential Modules
LoadModule proxy_module/usr/lib/apache2/modules/mod_proxy.so
LoadModule proxy_http_module/usr/lib/apache2/modules/mod_proxy_http.so
# Which user to run this Apache configuration as
User Www-data
Group Www-data
# These must to be set else the host isn ' t passed correctly
Usecanonicalname off
Proxyvia on
Proxyrequests off
# This must also to be set, though it's only a option in Apache2
Proxypreservehost on
# The Ip/port combination to listen on
Listen 9.20.1.1:80
# Using name-based Virtual hosting allows to host multiple sites per Ip/port combo
Namevirtualhost 9.20.1.1:80
# Configuration to forward requests for STARTUP.TLD
<virtualhost 9.20.1.1:80>
ServerName Www.startup.tld
Serveralias Startup.tld
Proxypass/http://127.0.0.2:10000/
Proxypassreverse/http://127.0.0.2:10000/
Proxypassreverse/http://www.startup.tld:10000/
Proxypassreverse/http://startup.tld:10000/
</VirtualHost>
# Configuration to forward requests for RECKLESS.TLD
<virtualhost 9.20.1.1:80>
ServerName Www.reckless.tld
Serveralias Reckless.tld
proxypass/http://127.0.0.2:10001/
proxypassreverse/http://127.0.0.2:10001/
proxypassreverse/http://www.reckless.tld:10001/
proxypassreverse/http://reckless.tld:10001/
</VirtualHost>
Be sure to pay attention to the proxypreservehost instructions here. This instruction is provided by Apache 2, which solves some of the problems of forwarding the correct HTTP headers to the backend server. Therefore, it is strongly recommended that you use the Apache 2 instance as a façade server.
Run the sample configuration
The root user should run each configuration. Apache obtains the privileges specified in the configuration file and uses them for all host-related processes. Listing 5 shows how to run the example.
Listing 5. Starting the sample server
/usr/sbin/apache-f/etc/apache/startup.tld.conf
/usr/sbin/apache-f/etc/apache/nimrod.tld.conf
/usr/sbin/apache2-f/etc/apache2/facade.tld.conf
Limitations of the Mod_proxy method
It is important to note that the methods described in this article do not apply to domains that require an SSL connection. This is because the SSL protocol does not allow domain virtual hosts. Because of this limitation, any SSL host must be executed in an appropriate manner so that each SSL domain uses its own combination of ip/ports. This restriction exists for all Apache configurations, and Apache, which uses this solution, is no exception. You can still run the SSL domain under their owner's user ID.
Conclusion
In this article, you use the Apache mod_proxy module to build an environment in which a façade server transfers requests to two backend servers. The same approach can be applied to a series of backend servers. This approach enables system administrators to reduce the potential security risks while maintaining the flexibility provided by tools such as PHP.