Go to the navigation

elblogg

<-->

Using apache to create an authenticated proxy

updated february 2009

whenever you are developing webservices or websites using Ruby On Rails or Python Django there’s times where you might like to make your service available to external users while you’re still using the integrated (development) webserver that comes with those projects. Or maybe you’ve been developing a service that’s using the SimpleHTTPServer to expose its functions to the local machine (by binding to the loopback interface) without any authentication or encryption mechanisms, and you want to expose these services to external hosts.

The Apache proxy and authentication mechanisms provides a simple way to get this in a well-tested way. (Don’t implement authentication yourself if you can use an existing and proven implementation).

This document describes how you would set up apache to act as a authenticated proxy ahead of your webservice. I will use the http basic access authentication and I will not go into encryption. Encryption and SSL is enough content for a complete article itself, and there should be plenty of such articles around.
Also note that your webservice still could be accessed directly from the machine that’s running the service, and you need to make sure that access from remote machines to the service is denied, by a blocking firewall or by the service just binding to the loopback interface (localhost or 127.0.0.1)

Enable proxying in apache

Verify that the mod_proxy (and mod_rewrite) modules are installed with Apache. These should be installed by default (but not enabled) in distributions like Ubuntu, Debian, OpenSuSE and CentOS. You can verify this by looking for the files mod_proxy.so and mod_rewrite.so in apache’s module directory.

The module directory is found here in the various distributions:

CentOS/Fedora/RHEL
/etc/httpd/modules/
Ubuntu/Debian
/usr/lib/apache2/modules/

If they’re not there you’ll need to install them, either by compiling them yourself or using your distributions package archive.

In any case, you’ll probably have to enable the modules. This is done differently in different distributions, so you can skip the sections below that are not for your distribution. If your distribution is not one of these (Debian, Ubuntu with derivates, CentOS, Fedora, RHEL), chances are that at least one of the approaches will work for your distribution with minor modifications.

Debian and Ubuntu (with derivates)

To enable a module in Debian or Ubuntu you create a to all files that are starting with that modules name in the /etc/apache2/mods-enabled/ directory.
In our case, we want mod_proxy and mod_rewrite and this can be done by issuing the following command:

sudo ln -s /etc/apache2/mods-available/proxy* /etc/apache2/mods-available/rewrite* /etc/apache2/mods-enabled/

and then restarting apache by issuing this command:

sudo /etc/init.d/apache restart

CentOS, Fedora and RHEL

These distributions should come with the required modules already enabled, and you can verify this by grepping the httpd.conf file like this:

grep -E "^\S*LoadModule .*mod_(proxy|rewrite).so" /etc/httpd/conf/httpd.conf

this should result in exactly two lines, like these:

?View Code APACHE
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so

If they’re not there, add the missing line(s) to the config file (without the prepending enumeration, preferably in the same section where other LoadModule-statements are located. (In my vanilla httpd.conf in CentOS 5.2 this is the lines 148 through 199)

Setting up the proxy

Now, there’s a million different ways to do this, you might want to have a seperate virtualhost for the service, you could let all traffic that comes to your apache server go to the service behind it (after authenticating the user), and you might even just apply the proxying to a seperate directory on the server.

In any case, the way I’m doing it here should work in all the above mentioned situations, you just have to place the configuration in different sections of the apache config.

Something to test with

Lets just start by starting a service you can test this with, go into a directory where all the files are safe to distribute online, if you don’t have such a directory, create one, and make a file inside it, stating hello world or something.

Now, assuming you have Python installed, issue the following command:

python -c "import SimpleHTTPServer;SimpleHTTPServer.test()" &

This will start a simple webserver, and serve the content of the current directory at port 8000 on the machine. To stop the server, issue the fg command, and press ctrl+c.

Configuring the proxy

First, we’re going to configure a proxy without authentication, that’s why the previous step was to start a non-sensitive service to test with.

Debian, Ubuntu and derivates

Open the configuration file for the virtualhost that you’d like to turn into this proxy (by default all hosts in a debian Apache config is a virtualhost, and if you only have one, it’s named “default”). Lets say you would like to turn the default host into the proxy, open /etc/apache2/sites-enabled/default.
Now insert the code from the “Configuration file content”-section below into the end of the <VirtualHost> section (I’ll go through the meaning of it later):

CentOS, Fedora, RHEL

Apache’s config file are located at /etc/httpd/conf/httpd.conf in RedHat-based systems. You may decide for yourself if you want to put the following code into this file, or if you want to put it into a new file in the /etc/httpd/conf.d-directory. Anyway, You need to put the code in the “Configuration file content”-section below into a VirtualHost directive, or a Directory-directive matching the document root where you want the proxied service to be served from. For example <Directory “/var/www/html”>….</Directory>

Configuration file content
?View Code APACHE
    <Proxy http://localhost:8000>
        Order Allow,Deny
        Allow from all
    </Proxy>
    RewriteEngine On
    RewriteRule test/(.*)$ http://localhost:8000/$1 [P]

By default Debians Apache config denies all proxy requests, therefore we need to explicitly allow the proxying of localhost port 8000, then we enable the URL-rewriting engine, which allows us to rconfigure the urls exposed in a flexible manner, The RewriteEngine On statement may be left out if it’s either mentioned before in the virtualhost configuration, or we’re using the ProxyPass directive instead of RewriteRule.
The RewriteRule decides what URL’s that should be passed on to the proxied server behind it. This is done with 3 parameters, the first parameter is a regular expression that matches the incoming request, the second is where the request should be passed on to, where $1-$9 is replaced with the match groups from the regular expression. Then the last parameter, in this case [P], tells Apache to proxy the request instead of just redirecting the client.

To proxy all incoming requests no matter what, just replace test/(.*)$ with ^(.*)$ which will match all incoming requests. You may even use this to limit access to specified features in the service behind it. Let’s say you have a REST service on the server behind the proxy, and you want to expose all the call to /events/ but not to, let’s say /bridge/.
This could be done with this RewriteRule directive:

?View Code APACHE
RewriteRule events/(.*)$ http://localhost:8000/events/$1 [P]

Adding authentication

Creating a user-file

we need to create a file, that will contain the users, and password-hashes to match against. This is done with the tool htpasswd:

htpasswd -c /etc/proxyusers.htpwd username

It will prompt two times for the password for the user, and save the file as /etc/proxyusers.htpwd
Subsequent users may be added with

htpasswd /etc/proxyusers.htpwd username

Note that there’s no -c, the -c tells htpasswd to create a new file.

Configuring authentication

In the same section where you did the changes above, inside the <Proxy>-section, add these lines (again, I will go through their meaning later):

?View Code APACHE
AuthType Basic
AuthName "Authenticated proxy"
AuthUserFile /etc/proxyusers.htpwd
Require valid-user

So the <Proxy>-section looks roughly like this:

?View Code APACHE
<Proxy http://localhost:8000>
    Order Allow,Deny
    Allow from all
    AuthType Basic
    AuthName "Authenticated proxy"
    AuthUserFile /etc/proxyusers.htpwd
    Require valid-user
</Proxy>

So, what did we do here? With AuthType Basic we’re telling apache to authenticate using Basic Authentication. The AuthName "Authenticated proxy" is merely the message displayed to the user when he/she is asked for username and password. AuthUserFile /etc/proxyusers.htpwd tells apache that the user “database” is in the file /etc/proxyusers.htpwd. Then, at last, we tell apache it’s sufficient that the user exists, and that the user is authenticated to let the request through with the Require valid-user statement. Instead of “valid-user”, we could also list all users that should be allowed access, or even use groups. See the apache auth howto for a more through description of your options.

Last, but not least

When you’ve got it working against the test-server, remember to stop the test-server, and change the ports (8000) in the configuration files as necessary.

One Response to “Using apache to create an authenticated proxy”

  1. elblogg » Blog Archive » New howto: Using apache to create an authenticated proxy

    [...] Using apache to create an authenticated proxy [...]

Leave a Reply

Bloggurat Twingly BlogRank Blogglisten