7.5. Advanced Web Servers with Jails

 < Day Day Up > 

Administrators rarely get to have the final say in what technologies their web servers must support. The web team will come to you with a demand for the latest, greatest PHPNuke-MySQL-ImageMagick-XML technology, and management will decree that it must be supported. Running Apache in a jail or chroot environment will help limit your server's exposure to vulnerabilities in the web applications. There have been vulnerabilities in Apache's httpd itself, too, and this will help protect you if you fall prey to an exploited vulnerability.

7.5.1. Using Jail or Chroot

Unfortunately, Apache does not support jail or chroot easily the way BIND does. It takes work. So, before we launch into configuring Apache in a jail, we have some planning to do.

Remember the difference between jail and chroot from Chapter 2. For convenience in this chapter we often say "jail" to refer equally to both environments. It means "jail" for FreeBSD administrators and "chroot" for OpenBSD administrators since only FreeBSD has jail. The instructions here only differ in the syntax of the command that launches the environment.


7.5.1.1 How many instances?

If you are hosting a single web server for an organization, you may only be concerned about one user group and one set of requirements. In that case you only need to jail your single instance of Apache. If you work for an ISP, or if you work in the IT department of a large organization, you may have many user populations to support. You might have to protect your server from the users and the user populations from each other. You might even have conflicting requirements; for example one user set might require PHP Version 4 while another requires PHP Version 5. In these kinds of situations you can create multiple instances in different jails. Just use different IP addresses for each server instance and they can stay separated.

It's decidedly simpler to chroot or jail a single instance of Apache, but if we do it well enough once, we should be able to repeat it. Many variables affect your decision about whether or not to chroot or jail and, if so, how many instances to run; so we will focus on how to chroot or jail a single instance. When there are problems that you will have to overcome in order to run multiple instances, we'll point them out and describe some potential solutions.

7.5.1.2 Building and installing into a jail

There are two ways to build: using the ports system and directly from the source. In Chapter 2, we discuss how to make a feature-rich jail that we build packages in, so that we can then install those packages in a minimal jail for execution. If your configuration is easily supported by the configuration options in the ports system and you're using FreeBSD, this is probably the best way to go. Building from source is also viable, and is necessary on OpenBSD. Chapter 2 contains an example of building Apache in a jail, so we will describe how to build Apache from source here.

There are dozens of ways that you can choose to configure Apache to run in a jail. We have picked one way that is effective and clear. Vary it according to your needs and preferences.


We will use /jail as our jail directory for our examples in this section. Recall from Chapter 2 that if Apache is looking for a file /etc/pwd.db, for example, then we will need to create /jail/etc/pwd.db.

We will give Apache's configure script a different base directory instead of /usr/local. Since we have to run make install during this process, we don't want our jail-friendly Apache to be installed on top of our real Apache that runs out of /usr/local. We will run Apache out of a /web directory. You will need to create a real /web at least temporarily in order to let the binaries install. If you want to create a symbolic link from /web to some other location in the filesystem, that will work. To configure Apache, then, we run a command like:

./configure --prefix=/web --enable-ssl

Your actual command will probably vary, based on what modules you need.

Now that it's configured, you can run make to perform the build, and make install to install into our /web staging environment. After the installation is complete, pare down the directory to eliminate detritus that comes from a general-purpose Apache installation. In /web you will find a man directory with manual pages, as well as a manual HTML documentation directory. You can probably delete these. You may also find the standard icons directory unnecessary unless you are using mod_autoindex as described later in this chapter. After you have removed all the files and directories you don't want from /web, copy what's left to /jail/web using a command like cp -pr /web/* /jail/web.

You will also see build, lib, and include directories in /web. At first glance, you might think they are superfluous, since you will only be running a server here. While you're right in thinking that they're not used at runtime, they are necessary if you plan on building Apache modules (e.g., mod_php, mod_perl, etc.). Though you may not need them in your /jail/web runtime environment, you will want them in your /web staging environment so you can use them later to build compatible modules.

7.5.1.3 Finding and adding support files

Apache needs additional files, present in your operating system, but not yet in your jail. Table 7-3 lists the files that you will need and indicates whether they are needed in FreeBSD, OpenBSD, or both. Note that the only part of the entire process that needs to be done as root is the making of the /dev/null device in /jail/dev/null. You can (and should) configure, build, and install Apache as an unprivileged normal user. For example, if you are creating multiple jails, you can have each jail's files owned by a different user.

Table 7-3. Files used in Apache jails

File

Location

Null device

dev/null

Maps UIDs to user IDs

etc/pwd.db

C runtime library

usr/lib/libc.so.34.1 (OpenBSD)

lib/libc.so.5 (FreeBSD)

Math library

usr/lib/libm.so.2.0 (OpenBSD)

usr/lib/libm.so.2 (FreeBSD)

Threading library

usr/lib/libpthread.so.6.0 (OpenBSD)

The runtime dynamic loader

usr/libexec/ld.so (OpenBSD)

libexec/ld-elf.so.1 (FreeBSD)

Cryptography library

usr/lib/libcrypto.so.11.0 (OpenBSD)

usr/lib/libssl.so.9.0 (OpenBSD)

lib/libcrypt.so.2 (FreeBSD)


By the time you try this, it is possible that something will have changed in either FreeBSD or OpenBSD or Apache to make these instructions incomplete. If, after installing these files, the server will not launch, it will probably tell you what library it needs. For example, you may see /libexec/ld-elf.so.1: Shared object "libdb4.so.0" not found. In that case, run ldd /web/bin/httpd and look for the library in the output. You will see output like: libdb4.so.0 => /usr/local/lib/libdb4.so.0 (0x280fc000). This means that you need to copy /usr/local/lib/libdb4.so.0 to a location in the jail, such as /jail/lib.

You may also want some files such as /etc/localtime, /etc/resolv.conf, and /etc/hosts. The /etc/localtime file will let Apache log entries in the correct time zone. The /etc/resolv.conf and /etc/hosts files influence how the processes in the jail resolve hostnames. However, if /etc/resolv.conf and /etc/hosts are omitted, they will resolve names using the default resolution in the regular (non-jailed) operating system. Refer to Table 2-4 for other files that you might want or need in your jail.

7.5.1.4 Launching httpd in chroot(8) on OpenBSD or FreeBSD

Before launching your chrooted httpd, ensure the IP address on which your Apache server will be listening is correct. With a single chrooted installation like this, the specification of IP address is unimportant. On systems with multiple instances of chrooted Apache servers, however, running them on separate IP addresses is imperative. You may even need to configure multiple IP addresses per chroot. This is certainly possible just make sure not to allow one chrooted instance to use another's IP.

IP specification boils down to adding a line such as Listen 12.34.56.78:80 to your httpd.conf file. See the Apache documentation for more information about the Listen directive. Once this has been done, you can launch the chrooted Apache process by running chroot /jail /web/bin/httpd -DSSL as root (either interactively, or in a script that is run by root at boot time).

While it's always easiest to have SSL-enabled Apache servers start automatically, you pay a small price in security to enable it. Ideally, the server's private key should be stored encrypted on the filesystem and should require a passphrase to decrypt it. Apache cannot start (even the non-SSL functions will not start) until it is decrypted. Your alternative, to enable automatic startup, is to leave your private key unencrypted in the filesystem. No one will need to be around to start the service, but your key can be compromised more easily.


7.5.1.5 Launching httpd in jail(8) on FreeBSD

If you are using Apache on FreeBSD, use jail instead of chroot whenever you can. Jails take the same amount of work to set up, but their security is more robust and thorough than chroot. As we mentioned in Chapter 2, jail requires quite a few arguments.

jail -u root /jail www.example.com 12.34.56.78 /web/bin/httpd  -DSSL

In this case we have explicitly said the jail will have to run as root. Apache needs to bind to port 80, and it can only do that if it starts off running as root. The next argument is the root of the jail filesystem, /jail. The next two arguments, the hostname and IP address, distinguish jail from chroot.

No process, not Apache, a CGI program, a PHP web page, or a malicious hacker's program that accidentally gets installed in the jail, can perform any network activity with any IP address other than the one assigned to this jail. Normally, if an attacker injected the right code into a vulnerable chroot or non-chrooted system, he could use raw sockets to spoof the source address of malicious packets. Or, he could try to sniff packets by opening the network device in promiscuous mode. None of these things are possible in a jail. We know that any mischievous activity will have the jail's IP address on it, so our network detection systems will have an accurate picture of the traffic (malicious or otherwise) going in and out of the jailed process. We also know that someone who compromises the jail thoroughly will still be significantly limited in what he can do, especially since we didn't install /bin/sh or any other shell in our jail filesystem. That step by itself dramatically limits an attacker's capabilities.

7.5.2. A Two-Tiered Architecture

For a powerful way to enforce separation of privileges and web site isolation, we propose a combination of Apache's mod_proxy with FreeBSD's jails or either operating system's chroot. If you run many web sites on a single host and you have many different users managing those sites (a situation that begs for FreeBSD and Apache), you can achieve a level of separation that will allow your users to have unprecedented control over their web configuration, yet will keep their mistakes from affecting other users.

Pictures are worth a thousand words, so let's start off our architectural discussion with Figure 7-6. It shows a general overview of the architecture, and will serve as a reference for sections to come.

Figure 7-6. General architecture of a multiple jail system


This architecture uses a frontend jailed Apache instance that exposes a single IP address to the Internet. This external jail uses mod_proxy behind the scenes to redirect traffic to internal jailed web server instances. Each of these internal jails is assigned a distinct RFC 1918 private IP address and is accessible only through Apache. Finally, in our example, each internal jail handles the web needs for a given organization. This makes our proxy rules easier to differentiate, but bear in mind that more complex configurations are certainly possible.

The rest of this section is devoted to a structured walkthrough of setting up exactly this configuration. Once you can handle this specific example, you should be able to carry the lessons you've learned onto more interesting scenarios.

7.5.2.1 Configure the internal jails

First off, create a jail for each organization as described in "Using Jail or Chroot." These jails should be configured with whatever modules and options they need but remember, enable only the modules you need. For example we set the ServerName in the two jails to jail.example.org and jail.company.com. Aside from setting this directive to something other than the one you really want to publish, configure everything else normally.

In order for Apache to access each jailed site, you'll want to assign names to them. Jailed web sites are configured with local, unroutable IP addresses (e.g., 10.0.0.2 or 192.168.0.5). You can either give each jail a name in DNS that maps to the associated IP address, or add an appropriate entry to /etc/hosts. In this example, we assign the name jail.example.org to IP address, 10.0.0.2 and jail.company.com to 10.0.0.3.

If you've been reading carefully, you'll note that we have not mentioned what web server is running within the jail. In fact, there is no reason why the jailed web site cannot run thttpd or some other web server software. Since the jailed web server does not know that it is jailed, any web server software should work just fine.

Now, in order for Apache to access the jail, you need to add aliases to your network interface. On FreeBSD, we insert two lines like this in /etc/rc.conf:

ifconfig_xl0_alias0="inet 10.0.0.2 netmask 255.255.255.255 ifconfig_xl0_alias0="inet 10.0.0.3 netmask 255.255.255.255

On OpenBSD, append the following two lines to /etc/hostname.xl0:

inet alias 10.0.0.2 255.255.255.255 inet alias 10.0.0.3 255.255.255.255

Of course, you will need to replace x10 above with the name of your network interface.

Your host is now accessible not only on the primary public IP address, but also on the two aliases 10.0.0.2 and 10.0.0.3. This may not be what you want. If your host is in a DMZ, you can use your local or network-based firewall to restrict access to these IP addresses so that no one in the outside world can connect directly to them. You might be wondering why you didn't just use the loopback (lo0) interface. By assigning routable IP addresses to your jails, you have created a convenient mechanism for expansion. You can move a jail from one host to another by migrating the jail's private IP to a new host. See "Modularity" for a little more information about moving internal jails.

7.5.2.2 Configuring the external jail

The external jail contains an instance of Apache that is essentially just a big dumb proxy. It blindly accepts and proxies traffic to the internal jailed web sites. For this external jail, you need Apache with mod_proxy, and probably very few other modules. The externally facing web server can run out of a jail or chroot as well. It's like creating a firewall/DMZ architecture in the middle of your host. For every web site you want to proxy, add a configuration block as shown in Example 7-13 to your httpd.conf. This tells Apache to proxy the requests to the internal jails.

Example 7-13. Proxying for two jails
<VirtualHost www.example.org>         ProxyPass         / http://jail. example.org/         ProxyPassReverse  / http://jail. example.org/         ProxyVia          On </VirtualHost> <VirtualHost www.company.com>         ProxyPass         / http://jail.company.com/         ProxyPassReverse  / http://jail.company.com/         ProxyVia          On </VirtualHost>

7.5.2.3 Jail versus chroot

We've used the term jail throughout this section, even though you might only have chroot available to you. If you have FreeBSD and can use jails, do. They are safer and harder to escape. Aside from the syntax of the command that launches the internal web server, however, the concepts are the same. The jail will need the same support files as a chroot environment will.

7.5.3. Advantages and Disadvantages

There are a lot of great advantages to this system, but it does create some management and maintenance concerns, too.

7.5.3.1 Ultimate separation

This scheme creates a great separation between different user bases. Now, if one set of users completely corrupts their web configuration or their pages, they will not affect the other users or the external proxy that handles routing requests.

WebDAV might be secure enough to use if each site's users are segregated into their own jails. Each jail will have its own filesystem, permissions, and configuration for authorization. Although all the users in a given jail have equal permissions on that jail's files, they do not have any access to the files in other jails. The users are partitioned from each other, and they get to use a protocol that integrates nicely with their development tools.

The separation is so complete that you might consider allowing advanced power users to control the httpd.conf file for their jailed server. After all, if they corrupt the file, only their site will fail.

7.5.3.2 Performance

It is clear that there might be a performance penalty to this architecture. Two servers, the external proxy and the jailed internal server, might handle every request. You can mitigate this problem somewhat by turning on caching at the external proxy. Then, static content such as stylesheets, images, and JavaScript files will be handled by the external proxy most of the time. Dynamic content can still be generated by the internal server, and it will suffer the small penalty of being handled by two servers.

7.5.3.3 Modularity

Each individual site is easy to migrate to new host hardware, when needed because it is completely self-contained in a jail. If a site gets too much traffic and needs to be migrated to a beefier host system, its jail can be copied wholesale to the new host, and that new host can be given the IP address associated with the jail. If you're using DNS for name resolution of this private address space, you're done!

It's easy to run different versions of web server software this way, too. Perhaps you want to try out Apache 2. Maybe your customers want significantly different module sets. Completely segregating configurations can turn very complex single Apache installations into several very simple ones. Since simplicity is easier to administer, you might prefer this route.

     < Day Day Up > 


    Mastering FreeBSD and OpenBSD Security
    Practical Guide to Software Quality Management (Artech House Computing Library)
    ISBN: 596006268
    EAN: 2147483647
    Year: 2003
    Pages: 142
    Authors: John W. Horch

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net