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.
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 allow, deny, and 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 order directive tells the server to process all allow directives before any deny directives. Astute readers will note that we don't have any deny directives, but bear with me, it becomes useful later. More importantly, the allow directive 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 deny directive:
<directory /usr/local/http/docs> <limit> order deny,allow deny from all allow from .mycompany.com </limit> </directory>The order directive suddenly becomes important. First, the deny directive restricts access to everyone. Then, the allow directive allows anyone whose machine name is part of the mycompany.com domain. 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.com domain, as well as any machine whose IP address starts with 192.153.22.
Some syntax details:
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 18.104.22.168 .kp </limit> </directory>This lets everyone in, except some person at 22.214.171.124 and any machine in North Korea (the .kp domain). Of course, that guy at 126.96.36.199 will move to 188.8.131.52 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 appropriate allow directives:
<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.