zxViperxz has asked for the wisdom of the Perl Monks concerning the following question:

For years I have been using modperl and have been quite fond of it, the idea of persistant perl interpereter is excellent.

The problem however lies with using modperl securely for multiple sites. Ideally, the desired solution is to have each site run in a chroot jail for security, have each site execute under it's own user/group and have a modperl instance for each site.

Up until now the best solution I have been able to come up with is as follows:

Implementation 1:
Top Level Apache Server, Port 80, ModProxy
This serves requests via ModProxy to the respective apache servers with mod_perl.
Site 1 Apache Server, Port 8081, ModPerl
This server runs an instance of ModPerl and all scripts required for Site 1.
Apache User: site1
Site 2 Apache Server, Port 8082, ModPerl
This server runs an instance of ModPerl and all scripts required for Site 2.
Apache User: site2
This allowed me to have seperate modperl instances, this is done for three reasons:
1) ModPerl does not support user based processes
2) This prevents polution between instances & secures one mod_perl instance from another.
3) Each instance can be chrooted for additional security.
The problem with this configuration is:
1) Requires a new http server for each additional site/modperl application
2) Apache creates a set of workers for each instance (ususally about 7). With 7 required for the Top level proxy, and 7 for each site, this soon adds up.
e.g. 5 sites = 7 + (5 * 7) = 49 child workers
---------------------------------

Implementation 2:
A new solution I have been working on is to have a single Apache server with chrooting suexec and speedycgi.

The setup is as follows:
1. Create a Chroot Jail for Apache (Extra Security Measure). 2. Modify suExec to allow chrooting before suid and process execution.
3. Install Apache into Chroot Jail
4. For each site:
a. Create a Jail for each site that includes perl + speedycgi
b. Create a virtualhost which specifies SuExecUserGroup and the ENV variable used for the chroot.
How it works:
Apache first resides in a jail, it then serves non-perl requests to static objects as per normal. When a request for a perl script is made:
Apache chroots into the site's jail using suexec. Suexec changes to the correct site's user.
SpeedyCGI then either:
Loads a script into speedy-backend or
Executes a script cached in speedy-backend
Advantages:
1) Provides persistant perl WITH suexec for per-virtualhost user execution
2) SpeedyCGI handles dynamic data, Apache handles static, hence you don't require a covering proxy as described in http://perl.apache.org/docs/1.0/guide/strategy.html
3) The timeout property in speedycgi means that a script with low or no load will drop out of memory, this means high use scripts will run in persistant perl and low use scripts will load into memory then remove themself when they are no longer being activly used.
Disadvantages:
1) Speedycgi seems to be no longer in development, whereas modperl is still in active development.
2) I have read somewhere that speedycgi is not as fast as modperl (will have to benchmark the two later).
3) Since speedycgi with timeout enabled fades out with inactivity, the first request to an inactive script requires all the modules to be reloaded, whereas modperl exists in memory indefinitly and can load a script on server start, rather than first request.
---------------------------------

I was wondering if I could get some feedback on both these designs. I have been researching and testing the second solution over the last few days and would like to get some input.

a) Is there a better way to achive this goal?
b) Is there a way to make modperl scale and attain the desired results without creating a new server for each instance (Implementation 1)?
c) Have I missed anything (security etc. (Implementation 2))?
d) Is there a better solution (fastcgi/pperl etc.)?
e) What are there any downsides (other than those listed above) to either of these implementations?

Finally, as wise perl monks are there any suggestions/ideas?

Sorry if I posted this in the wrong section, this lies somewhere in between meditation & seekers of wisdom)


James Austin
  • Comment on Apache (httpd) + Persistant Perl (ModPerl/SpeedyCGI) + User Based Processes (SuExec) + Chroot

Replies are listed 'Best First'.
Re: Apache (httpd) + Persistant Perl (ModPerl/SpeedyCGI) + User Based Processes (SuExec) + Chroot
by pc88mxer (Vicar) on Jun 23, 2008 at 14:55 UTC
    Just two quick comments:

    1. chroot is not very effective as a security measure. For instance, see How to break out of a chroot() jail.

    2. I'd bounce these ideas off of the modperl mailing list (modperl@perl.apache.org).

      Thanks for the comments.

      The exploit you pointed out, requires a user to have root privledges to be able to break out of the Jail. The only point where root priveldges are used is when suExec performs the user change and the chroot which is done via a SUID bit.

      SuExec prevents changing to a user with a GID/UID < 100, so as long as suExec is secure (which, due to it's simplicity it ususally is), that exploit should be blocked off.

      As for the modperl users tip, I shall go post this question there now.

      James Austin.