The Apache web server is by far the most popular web server platform in use on the Internet today. It has been ported to a plethora of operating systems. Unlike any other competing commercial web server, it is entirely open-source. Because of the openness of the design, many powerful modules have been developed which extend Apache functionality enormously.

Apache is a major centerpiece of Red Hat Linux 6.0. However, the web server is configured very differently from a standard Apache installation. This difference is so profound that some have begun to describe it as part of the “Red Hat Way.”

Basic Apache Configuration

If Apache is compiled from source, it will usually install to the directory /usr/local/etc/httpd. This directory does not even exist in a fresh Red Hat Linux installation.

Following is a brief map of various Apache files and directories under Red Hat Linux:

Virtual Hosts, with and without IP Alias

Virtual Hosts with IP Alias

A full discussion of this subject under Linux is available in the IP-Alias-HOWTO. This file can be found in a HOWTO RPM distribution on the accompanying CD or from any of the online Linux documentation resources (such as

Assuming, however, that a Linux system's eth0 Ethernet interface has been configured with IP address, the following commands will configure eth0 to respond to as well (which is central to establishing a virtual host):

/sbin/ifconfig eth0:1
/sbin/route add -host dev eth0:1

Obviously, no other machine on the network should be using the IP address If unsure, do not guess; check with the administrator.

These commands should be added to the system boot scripts. Be certain that they execute after the main ifconfig command(s) (a good place might be /etc/rc.d/init.d/network).

A sequence can begin with eth0:1 and continue to eth0:2, eth0:3, eth0:4... This allows several virtual IP addresses on one network interface -- up to 255.

Once the additional IP addresses have been added to the interface, DNS entries should be added with address records that point to the new entries (which is discussed earlier in this text).

The web server must now be configured to serve a different document root to each different IP address.

This behavior can be initiated with the Red Hat Linux Apache server by adding the following lines to the end of /etc/httpd/conf/httpd.conf:

DocumentRoot /home/luser/public_html
ErrorLog logs/luser-error_log
TransferLog logs/luser-access_log
RefererLog logs/luser-referer_log
AgentLog logs/luser-agent_log

A number of the above items must be changed for a real installation. The directory of the document root, the server name, and the names of the log files should be customized.

The Apache documentation suggests that the argument to the VirtualHost directive be an IP address, not a host name. If DNS should be unavailable for some reason when Apache is started and the VirtualHost directives cannot be resolved, they will be ignored.

Name-based Virtual Hosts

The HTTP/1.1 protocol supports a mechanism where the web server can obtain the name that the browser used to access the site. Apache can be configured to serve multiple web sites based upon this retrieved name, even when the DNS resolution of the sites all point to the same IP address.

The Apache configuration for such an arrangement is only slightly different from IP alias:


DocumentRoot /home/luser/public_html
ErrorLog logs/luser-error_log
TransferLog logs/luser-access_log
RefererLog logs/luser-referer_log
AgentLog logs/luser-agent_log

There is also a ServerPath directive that can be used to compensate for older browsers that are not compliant with HTTP/1.1 (such as MS Explorer 2, which is shipped with Windows NT 4). The ServerPath directive takes a directory as an argument. This directory is relative to the document root. When files within this directory are requested, they are assumed to belong to this host.

Virtual Hosts with JavaScript

The best method to establish virtual hosts is to configure the server network card with multiple network addresses, as this technique will work with all browsers. There is, however, an alternative method that can be used with JavaScript-enabled browsers.

Let us imagine that the server network card is configured with a single IP address, and that the names and both resolve to this same IP address.

Let us further imagine that there is an index.html file in the document root of the Web server, and that this document root must be used to serve different pages for the different companies.

The JavaScript location variable contains the URL used to access the current page. In addition, if location is modified, the browser will immediately load the new URL contained within the variable.

The JavaScript to exploit this feature for virtual hosts could be as simple as:

<script language="JavaScript">


if (location=="")



With this approach, the browser, not the server, makes the decision as to which page to load.

JavaScript will clean up the location variable to some extent, insuring that it contains the http:// and a trailing slash.

This method is quite handy for Webmasters who do not have full administrative control of their machine. It is much easier to apply a change to one file than perform extensive reconfiguration of the network interfaces.

The greatest drawback is that non-JavaScript-aware browsers (such as Lynx) will not execute the script and load the new page, nor will JavaScript-aware browsers (Netscape 2 and later versions, Internet Explorer 3 and later), if JavaScript has been disabled by the user.

However, there are some other problems with this approach:

  1. To some degree, the browser will render the HTML of the main page before the location is changed to the alternate page. To minimize this effect, place the above JavaScript near the beginning of the <HEAD> tag.
  2. The history list will contain the original URL, not the redirected location.
  3. If the user presses the browser's Back button, the original URL will be reloaded, which will immediately redirect. This essentially disables the use of the Back button.

The JavaScript replace() method offers enhanced flexibility. After the replace() method is executed, the user cannot navigate to the previous URL by pressing the Back button. Unfortunately, replace() is not supported in any of the Netscape Navigator 2 releases, so version tests must be performed. Following is an example using replace():

<script language="JavaScript">


var js_ok = false;

if (navigator.appName.substring(0,9) == "Microsoft" &&
        parseInt(navigator.appVersion) >= 4 )
        js_ok = true;

if (navigator.appName.substring(0.8) == "Netscape" &&
        parseInt(navigator.appVersion) >= 3 )
        js_ok = true;

        if (location=="")
                if (js_ok == true)



Static Password Protection

Applying password protection to a web page is a relatively easy process. This simple form of web security requires the creation/modification only a few files on the web server.

These basic security features are configured through the use of an .htaccess file. The settings in this configuration file apply to all HTML files that lie in its directory and subdirectories.

It is important to understand the limits of this type of protection. It is not very secure. It can be easily be abused. Do not trust an .htaccess file to protect critical data.

Web pages protected by an .htaccess file must be readable by the userid of the web server - usually userid nobody, group nobody. Unless the author of the web pages has configured the web server and the pages to share their own group (which cannot be done without the aid of the super user, assuming that the server runs at the standard port), the pages must have world-readable permissions to be visible to the web server. If such permissions are set, then any other user on the system with shell access can read the pages, regardless of the presence of an .htaccess file. Furthermore, CGI applications (specifically PHP, discussed in a later chapter) have access to this world-readable data.

Also, it should be remembered that all standard HTTP data will pass over the intervening network in clear text - unless SSL is configured (which is beyond the scope of this text), there is no encryption. This data can be intercepted by a packet sniffer (such as sniffit), or siphoned from a proxy cache.

Bearing these warnings in mind, a cursory discussion of this method of access control will follow.

The default Apache configuration in Red Hat Linux 5.2 does not allow .htaccess files to be used. To enable the use of these files for authentication, a change must be made to /etc/httpd/conf/access.conf. The change must be applied to a line in the <Directory /home/httpd/html> section in the file that begins with the words “AllowOverride” and ends with a series of options. At the very least, the line should contain the following:

AllowOverride AuthConfig Limit

Rather than the above permissions, the keyword All can be used to enable extensive control with .htaccess. Do not enable these extra features unless this functionality is actually required.

The AllowOverride statement occurs three times in the default /etc/httpd/conf/access.conf file: once for global options, once for executing programs from /cgi-bin, and once for all pages beneath the document root. Each section is enclosed within a <Directory> tag. Modify only the section for which access control is required.

Once these changes have been made, the web server must be restarted. This can be done either by sending a HUP signal to the master web server, or by cycling the web server with the rc files:

/etc/rc.d/init.d/httpd restart

Once the web server has reread its configuration files through a HUP or a restart, the security features will be enabled. To create a sample web page to test these features, execute the following commands as root:

mkdir /home/httpd/html/restrict
echo "<hr>HTML Rules<hr>" > /home/httpd/html/restrict/test.html

This file can be viewed locally with the URL (obviously, a qualified host name will be required for non-local browsers).

To protect this file and everything in its directory, create the following file as /home/httpd/html/restrict/.htaccess:

deny from all
allow from
AuthType Basic
AuthUserFile /etc/httpd/htpasswd
AuthName "special directory"
require valid-user
satisfy any

After this file has been created, enter the following command:

/usr/bin/htpasswd -c /etc/httpd/htpasswd bogususer

The system will ask for a password - enter one, then confirm it. Now examine the file /etc/httpd/htpasswd - it will be similar to this:


If all of these steps have been performed correctly, viewing the URL with a browser will require a name and password.

The file above actually allows unrestricted access from any requests originating from “” (which will require reverse DNS to function properly). An IP address can also be used in this position. If no unrestricted access is to be allowed, simply remove the allow line completely.

The htpasswd file can hold multiple accounts and passwords. To add another account and password to the file, enter the following command:

/usr/bin/htpasswd /etc/httpd/htpasswd realuser

After entering a password for this user, /etc/httpd/htpasswd will contain another line:


A number of users with individual passwords may be added in this manner. The Apache documentation warns that access will become very slow if an htpasswd file grows large. The problem of large lists of authorized users can be solved by moving the htpasswd data into a database. The Apache documentation recommends DBM files (which are not covered in this text), and authentication against a Sybase database is discussed in chapter seven of this text.

As a final note, astute users might have noticed that the entries in an htpasswd file are similar to the /etc/passwd database (or /etc/shadow, if the pwconv utility has been executed) which holds information about all users. In fact, the same password encryption technique is used (DES, not MD5) in both files, and it is possible to move the password hashes freely from one file to the other.

An inexperienced administrator might be tempted to synchronize /etc/passwd and an htpasswd file, or make a call directly from an .htaccess to /etc/passwd. Be warned, however, that such a configuration is a welcome door for an attacker, and the practice is best avoided.