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.
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:
/etc/httpd/conf - This directory contains the three
critical Apache configuration files:
httpd.conf - Main web server configuration
access.conf - Access restrictions and security
srm.conf - MIME and file associations
/var/log/httpd - The following web server logs reside here:
access_log - records all connections to the web server.
error_log - reports problems encountered by a running
server (CGI, .htaccess misconfigurations, etc.).
/etc/mime.types - Apache uses this file to associate
content types with filename extensions.
/etc/rc.d/init.d/httpd - This script should be used to
start and stop the web server. It should be called with an argument of
start or stop (a message to this effect
will be generated if the script is executed without an argument).
/usr/sbin/httpd - This is the location of the binary
program copy of the web server. This directory also contains several
web server support utilities (such as htpasswd, discussed
later in this chapter).
/home/httpd/html - This is the document root
directory. Files and directories placed under this directory will be
visible to the web.
The index.html file contained within this directory is seen
by default when a web browser attaches to the Apache server.
/home/httpd/cgi-bin - Files containing program
code which can be executed can be placed within
this directory. Programs that run from this location must conform to the
CGI specification, but can be written in almost any language, including
compiled C/C++ code, Java, Perl, PHP, BASH scripts, awk, or any other
compiled language or script interpreter. These scripts will be executed
by the nobody userid, so permissions issues are usually a
concern. CGI programs implemented without care are a grave security risk.
/home/luser/public_html - Each user on the system can have
their own space on the web server by creating a public_html
directory immediately off their home, and modifying their home directory
permissions to allow directory scanning privledges. For example, the
local user luser could create a personal web space with the
following commands:cd ~
chmod o+x ~
mkdir public_html
echo '<b>Sample HTML file</b>' > public_html/index.htmlhttp://127.0.0.1/~luser/index.html (substitute a fully-qualified
domain name for localhost if one is applicable).
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 http://www.linuxhq.com).
Assuming, however, that a Linux system's
eth0
Ethernet interface has been configured with IP address 1.2.3.3,
the following commands will configure
eth0 to respond
to 1.2.3.4 as well (which is central to establishing a virtual host):
/sbin/ifconfig eth0:1 1.2.3.4 /sbin/route add -host 1.2.3.4 dev eth0:1
Obviously, no other machine on the network should be using the IP address 1.2.3.4. 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:
<VirtualHost 1.2.3.4> ServerAdmin webmaster@luser.com DocumentRoot /home/luser/public_html ServerName www.luser.com ErrorLog logs/luser-error_log TransferLog logs/luser-access_log RefererLog logs/luser-referer_log AgentLog logs/luser-agent_log </VirtualHost>
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.
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:
NameVirtualHost 1.2.3.4 <VirtualHost 1.2.3.4> ServerAdmin webmaster@luser.com DocumentRoot /home/luser/public_html ServerName www.luser.com ErrorLog logs/luser-error_log TransferLog logs/luser-access_log RefererLog logs/luser-referer_log AgentLog logs/luser-agent_log </VirtualHost>
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.
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
www.company-a.com and www.company-b.com
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=="http://www.company-b.com/")
location="http://www.company-a.com/company-b/"
//-->
</script>
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:
<HEAD> tag.
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=="http://www.company-b.com/")
if (js_ok == true)
replace("http://www.company-a.com/company-b/")
else
location="http://www.company-a.com/company-b/"
//-->
</script>
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
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
http://127.0.0.1/restrict/test.html (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 permitted.com 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:
bogususer:TPNWusI5zZdqs
If all of these steps have been performed correctly, viewing the URL
http://127.0.0.1/restrict/test.html with a browser will require
a name and password.
The file above actually allows unrestricted access from any requests
originating from domain.com (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:
bogususer:TPNWusI5zZdqs realuser:Mv19hxh2ff07k
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.