Securing your Web server
Stop the wrong people from accessing your site!
Securing your Web server is easy, quick, and pays off big in terms of document safety. Don't let the fabulous content on your site be compromised by inadequate security. (2,000 words)
But before we dive in, I want to revisit my April column where we explored your server's agent log. In that column, I showed how to determine which browsers were being used to access your site and presented some charts showing the growth of Netscape 2.0 and the apparent decline of Microsoft's Internet Explorer. Thanks to an alert reader, I've got some interesting new data on some shady behavior on the part of Microsoft. Read all about it in this April column update. But make sure to come back when you're finished!
Everyone back? Great! Let's get started.
When you bring your server online and start soliciting visitors, you instantly increase the chances of your server being penetrated by some hacker. Why? Because your site is now well-known, promiscuously offering content to the world. Of the millions of machines on the Net, a very small percentage are actually Web servers. Since hackers tend to focus on machines where they may find something useful, any Web server is a better target than an anonymous machine sitting on someone's desk somewhere.
This means that you must not only secure your Web server and documents, you must also secure your machine against all other sorts of hacks and queries. Fortunately, SunWorld Online's very own Peter Galvin has done an excellent job covering the basics of server security, starting with his April column and concluding in May. Follow his advice and your machine will be well on its way to being impervious to most network-based security attacks. In particular, make sure you install tcp_wrapper and carefully configure external access to your machine.
The httpd security model
Now you're ready to configure the security features of your Web server. In order to do that, you need to understand how httpd and its derivatives, including NCSA's httpd and the Apache server handle server security.
Each time a user connects to your site, the client passes to the server the numeric IP address of the client machine. In some cases, this may be the IP address of a proxy server, requesting the document on behalf of some other machine. The http protocol also allows the client to provide the name of the user making the request, but this rarely happens. As a result, the only bit of data the server has to validate the request is the IP address of the client machine.
The first thing the server does is reverse this numeric address in an effort to get the textual domain name of the machine. This is the name that is human-readable, like www.sun.com. The reversing process involves contacting a domain name server, presenting it with the numeric IP address, and getting the domain name in return.
Surprisingly, many machines on the Net are not correctly configured to have their IP addresses reversed. This is not the fault of the machine, per se, but of the domain name server responsible for that machine's domain. Many network administrators get the forward maps (mapping the name to the IP address) correct but fail to configure the reverse maps (which perform the opposite mapping). As a result, this attempt to reverse the IP address may fail. Undaunted, the server forges ahead anyway.
Once the server has the client's IP address, and possibly its domain name in hand, it begins applying sets of rules to determine if this client can access the document in question. This IP-based rule model is at the heart of Web server security, enhanced only by password protection (which we'll cover in August).
Configuring the access.conf file
At the server level, document access is controlled by entries you put in your server's access.conf file, usually located in the conf directory at the top level of your server's installation directory. Within this directory, you can specify access rules for any directory within your server's document directory.
For each directory you want to control, you need to put a
<directory> tag into the access.conf
file. Within the
<directory> tag you'll use a
<limit> tag with its
order parameters to control access
to the directory.
Let's start with a simple example: Opening up your server so that the whole world can access files in your top-level document directory.
<directory /usr/local/http/docs> <limit> order allow,deny allow from all </limit> </directory>The
orderdirective tells the server to process all
allowdirectives before any
denydirectives. Astute readers will note that we don't have any
denydirectives, but bear with me, it becomes useful later. More importantly, the
allowdirective tells the server to allow access from any client address.
Suppose you're implementing one of those nifty new intranet things that
are suddenly all the rage (I guess "private WAN" or "local area network"
didn't sound cool enough to catch on years ago), and you need to restrict
access to just the folks in your company. Now, you'll need a
<directory /usr/local/http/docs> <limit> order deny,allow deny from all allow from .mycompany.com </limit> </directory>The
orderdirective suddenly becomes important. First, the
denydirective restricts access to everyone. Then, the
allowdirective allows anyone whose machine name is part of the
mycompany.comdomain. All other machines are denied access.
IP address reversal is now critical to gain access to your server. If the IP address cannot be reversed, the server cannot decide if a machine is part of your domain. It errs on the conservative side and denies access to the client. If someone in your company has a misconfigured domain name server, they'll soon be on the phone complaining that they can't reach your pages, and it's all your fault.
If you run internal servers for a large company, like I do, you might get ten calls a week from irate customers who can't reach your pages. The right solution is to force these people to contact their DNS administrator and fix the IP reversal problem. The quick and dirty solution is to add raw IP numbers to the access list:
<directory /usr/local/http/docs> <limit> order deny,allow deny from all allow from .mycompany.com 192.153.22 </limit> </directory>This minor modification allows accesses from any machine whose name reverses into the
mycompany.comdomain, as well as any machine whose IP address starts with
Some syntax details:
Now that those details are out of the way, here's some advice:
access.conffile after the server has started, your changes will not take effect until the server is stopped. To make life easier, most servers will reread the file when sent a HUP signal. Check your server's documentation for more details.
Managing multiple directories
You'll note that the
<directory> directive has a
specific directory name attached to it. If you have multiple document
directories on your server, you should have a
directive for each one. Further, each directory can have a completely
different set of access rules.
For example, to create a world readable top-level directory and a company-private directory within it, you could use:
<directory /usr/local/http/docs> <limit> order allow,deny allow from all </limit> </directory> <directory /usr/local/http/docs/private> <limit> order deny,allow deny from all allow from .mycompany.com </limit> </directory>The granting of access permissions is managed all the way down the directory tree. A user must have access to all directories above a particular one to gain access to that directory. Security is usually more restrictive as you go down the directory structure; it makes no sense to allow broad access within a subdirectory when the top-level directory has greater restrictions.
Dealing with individual control
Often, you will need to restrict access to a particular machine or classes of machines. Perhaps some malcontent is spamming your server, or you are required by federal law to restrict the dissemination of certain information (companies bound by ITAR restrictions on the export of sensitive technology are an example). Selective use of the
deny directive makes this easy:
<directory /usr/local/http/docs> <limit> order allow,deny allow from all deny from 22.214.171.124 .kp </limit> </directory>This lets everyone in, except some person at 126.96.36.199 and any machine in North Korea (the
.kpdomain). Of course, that guy at 188.8.131.52 will move to 184.108.40.206 next door to his office, and the folks in Korea will simply switch to an open proxy server in Europe before hitting your site. If you've got really sensitive stuff you need to restrict, I'll cover better solutions in August.
You can also grant individual access. Suppose you want to allow
access to your private pages to some strategic partner. Use
<directory /usr/local/http/docs/private> <limit> order deny,allow deny from all allow from .mycompany.com allow from .partner.com </limit> </directory>The best way to see how this works is to create a few test directories on your server and change their access rules. Once you get the hang of it, make sure you create appropriate rule sets for every directory on your server.
Next month, we'll look at other ways to control directory-level access, and I'll reveal a few quick URLs guaranteed to expose the dirty laundry hidden away in almost every Web server.
About the author
Chuck Musciano has been running Melmac and the HTML Guru Home Page for two years, serving up HTML tips and tricks to hundreds of thousands of visitors each month. He's been a beta-tester and contributor to the NCSA httpd project and speaks regularly on the Internet, World Wide Web, and related topics. His book, HTML: The Definitive Guide, is currently available from O'Reilly and Associates.
If you have technical problems with this magazine, contact firstname.lastname@example.org