Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Improve LAMP security with Apache Proxy's directive (mod_proxy)

Virtual hosting with multiple user IDs is possible

Nick Maynard (nick.maynard@uk.ibm.com), Scenario Analyst, IBM
Author photo
Nick Maynard has worked in the Scenario Analysis Lab at IBM Hursley since joining IBM UK Ltd. as a graduate in 2003 from the Imperial College of Science, Technology, and Medicine. He specializes in Linux, Web services, and business integration technologies. Contact Nick at nick.maynard@uk.ibm.com.

Summary:  In this article, Nick Maynard outlines a method for you to improve the security of a LAMP setup by using Apache's mod_proxy module. This article is specific to Linux; however, you can also apply some of the principles to other operating systems.

Date:  29 Nov 2006
Level:  Intermediate
Also available in:   Chinese  Russian  Japanese

Activity:  19508 views
Comments:  

The Apache Software Foundation's HTTP server project, commonly known as Apache, is the dominant Web server on the Internet today, accounting for over 60 percent of market share. Increasingly, the Apache serve is part of a set of free software programs in a configuration known as LAMP, a Web platform built on the open source technologies of Linux®, Apache, MySQL, and PHP. In this article, you'll explore a method that improves the security of your LAMP installation by using the mod_proxy module and multiple back-end servers. I'll discuss the merits and drawbacks of such an approach, and you'll see an example configuration of a working setup.

PHP and Apache: The security conundrum

One challenge that faces LAMP administrators is that of providing all the features of a full PHP installation while ensuring a secure environment for all users of the system. Use of PHP's safe mode is one technique for meeting this goal, but it can also unduly limit users, and some PHP applications simply don't function with this facility enabled.

The root of the PHP security problem lies in the way most Apache servers are configured. Because most Apache installations run under a special www-data user ID, all the users hosting a Web site must by default ensure that their files are readable by this user. Consequently, it is possible that all of a user's Web-accessible files will be accessible by all of the other users on the system, and as such could be subject to attack by an otherwise unrelated compromise on the system. The situation becomes even more untenable when files or directories must be set as writable by the www-data user.

With CGI programs, such as those written in the popular languages Perl and Python, you avoid some of the impact of this problem when you use the suEXEC mechanism. In short, suEXEC uses a special intermediary program to execute the CGI program as the user ID that owns the program. (See Resources for links to articles with more details.) This is a very effective mechanism and has been commonplace for many years.

However, PHP pages, when hosted using the mod_php module, are executed as part of the main Apache process. As such, they inherit all the credentials of the Apache process, and so any work they perform on the filesystem must be performed as the www-data user.

Running Apache under multiple user IDs

The obvious solution to the problem described above is to host all the requests for a user's domains from an Apache instance that has only that user's credentials. You can configure Apache to take on any user's credentials on startup. This can solve the problem for simple setups where each user is assigned an individual IP address/port combination visible to the Internet.

For more complex setups, where IP addresses are at a premium, this method will not work. You can only use virtual hosting, a technique widely used in Apache installations, when a single Apache instance has control of a particular IP address/port combination. This precludes the possibility of hosting multiple domains belonging to multiple users from the same IP address/port combination.

Apache 2.0 introduced the concept of multiprocessing modules, or MPMs. Among the MPMs provided with the basic Apache 2.0 package was an experimental module named perchild, which allowed virtual hosting under multiple user IDs by assigning a distributor thread to the IP address/port combination, and passing requests onto satellite threads that run under individual users' credentials. Sadly, perchild remained experimental, functioning only for the fortunate, and was eventually removed from the official Apache distribution with the release of Apache 2.2. Before this, realizing the continued need for a stable and functioning perchild-like MPM, the wider Apache community started work on a number of MPMs to fill the gap. MetuxMPM, and its process-oriented fork, peruser, continue to work towards this goal. (See Resources for more information on the MetuxMPM and peruser MPMs.)


A solution: mod_proxy

Although no official Apache MPM is available to directly provide virtual hosting under multiple user IDs, you can still build an Apache system that behaves in this way through some intelligent configuration and administration. The core concept of the method is the use of the mod_proxy module, which, among other functionality, allows Apache to forward requests for pages onto other servers, and pass the response back to the original requesting client.


Listing 1. Sample 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 a host's /foo hierarchy to the corresponding page hosted at http://foo.example.com/bar. For example, the page /foo/index.htm would be forwarded to http://foo.example.com/bar/index.htm. You can use this principle to solve the problem.

Example scenario

Consider a scenario in which an Apache administrator must host two domains for two separate customers. One customer is a startup online business that is concerned about online security. The other is an individual customer who is lax about site security and is known to upload insecure code to his site. Given these factors, the Apache administrator must take steps to isolate the two sites from each other.

The administrator therefore has two domains: www.startup.tld, owned by the startup online business (user ID startup), and www.reckless.tld, owned by the individual (user ID nimrod). To solve the problem, the administrator decides to use the mod_proxy solution. The administrator gives each user his own Apache instance running under his own user ID on a private IP address/port combination, and uses the mod_proxy solution to provide access to both users' domains through a facade server running as www-data on a public IP address/port combination. The complete scenario is illustrated in Figure 1.


Figure 1. Example scenario
Example scenario

Recommended Apache versions

For each element of the configuration of our sample application, the Apache administrator should use the versions of Apache outlined in Table 1.


Table 1. Versions of Apache used in sample application
ElementApache versionReasoning
Facade serverApache 2, running the worker or event MPMApache 2 features important enhancements to the mod_proxy module. The worker and event MPMs are threaded and help reduce the memory overhead of the facade server.
Back-end serversApache 1.3, or Apache 2 running the prefork MPMThe Apache administrator must be aware that the PHP module should not run under a threaded environment. These two solutions offer process-based environments for the PHP module.

Configuration for back-end Apache instances

The snippets in Listings 2 and 3 illustrate the essential configuration points that vary from a standard Apache configuration. They should be added to as required -- the example configuration omits PHP functionality, for example.


Listing 2. Apache config for startup online business
# 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 be 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 you 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 facade 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 config for individual customer
# 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 be 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 you 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 facade 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 for the facade Apache instance.


Listing 4. Apache config for the facade 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 be set else the host isn't passed correctly
UseCanonicalName Off
ProxyVia On
ProxyRequests Off
# This must also be set, though it's only an option in Apache2
ProxyPreserveHost On    

# The IP/port combination to listen on
Listen 9.20.1.1:80

# Using name-based virtual hosting allows you 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>

It is important to note the ProxyPreserveHost directive here. This directive came with the release of Apache 2, and solved some problems with forwarding the correct HTTP headers to the back-end servers. It is highly recommended that you use an Apache 2 instance as the facade server.

Running the example configurations

The root user should run each of the configurations. Apache will take on the privileges indicated in the configuration file for all hosting-related processes. Listing 5 illustrates how you'd start things up.


Listing 5. Starting the example servers
/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 approach

It is critical to note that the method outlined in this article will not work for domains that require SSL connections. This is because the SSL protocol does not allow for virtual hosting of domains. Due to this limitation, any SSL hosting must be performed in a manner whereby each SSL domain is hosted on its own IP/port combination. This is a limitation of all Apache configurations, not exclusively those utilizing this solution. You can still run SSL domains under their owner's user ID.


Summary

In this article, you used the capabilities of Apache's mod_proxy module to construct an environment consisting of a facade server forwarding requests to two back-end servers. You can use the same principle for a series of back-end servers. The approach allows system administrators to isolate potential security risks while maintaining the flexibility that tools like PHP provide.


Resources

Learn

  • suEXEC support: Get the documentation straight from Apache and learn how to reduce security risks when your users develop and run private CGI or SSI programs.

  • MetuxMPM Wiki: Learn about this module and contribute to the Multi Platform Module (MPM) for the Apache Web server (and successor to the Perchild MPM).

  • Introduction to LAMP technology (Jono Bacon, developerWorks, May 2005): Delve into this tutorial, a good intro to the Linux-Apache-MySQL-PHP, or LAMP, Web development framework as you solve common business problems.

  • developerWorks Web development zone: See more articles from developerWorks on LAMP and other Web development technologies.

  • Linux zone: Check out this developerWorks resource for up-to-date Linux technologies.

  • Technology bookstore: Browse for books on these and other technical topics.

  • developerWorks technical events and webcasts: Stay current with jam-packed technical sessions that shorten your learning curve, and improve the quality and results of your most difficult software projects.

Get products and technologies

Discuss

About the author

Author photo

Nick Maynard has worked in the Scenario Analysis Lab at IBM Hursley since joining IBM UK Ltd. as a graduate in 2003 from the Imperial College of Science, Technology, and Medicine. He specializes in Linux, Web services, and business integration technologies. Contact Nick at nick.maynard@uk.ibm.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development, Linux, Open source
ArticleID=172718
ArticleTitle=Improve LAMP security with Apache Proxy's directive (mod_proxy)
publish-date=11292006
author1-email=nick.maynard@uk.ibm.com
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers