Apache can be used as a reverse proxy - that is, it allows access to internal sites from an external network, such as the Internet.

NOTE This can lead to a security flaw, if you leave your apache unsecured and enable all proxying, you will act as an open relay. Be warned!

There are a few different ways you can use apache to proxy, such as:

  • mod_rewrite
  • mod_proxy
  • mod_proxy_html


mod_rewrite will rewrite a source URL transparently to the end user. AddToMe


mod_proxy is useful for simple proxying rules, such as when you want to expose a flat directory to the world, or if the internal site only uses relative URLs

For example, I have an internal network appliance (a camera) with a very simple web interface, that I wish to expose to a (properly authenticated) Internet:

        <IfModule mod_proxy.c>
                ProxyRequests Off
                <Location /camera>
                        AuthType Basic
                        AuthName "Camera"
                        AuthLDAPUrl ldap:///dc=internal,dc=org?uid
                        Require user daniel camera

"ProxyRequests Off" disables arbitrary proxying - this stops my webserver being an open relay. I've also configured the /camera location to require some specific auth, authing out of an LDAP tree on localhost.

"ProxyPass" is actually shorthand for "ProxyPass /camera". I can make this shorthand because the ProxyPass directive is inside a <Location> block. This says to proxy any requests for for /camera/* to*

ProxyPassReverse, which has the same syntax as ProxyPass, will adjust the response URI to keep it pointing at the same place.

This works fairly well, although it fails if the internal website is a bit more complicated, or is on a different port. Use mod_proxy_html for that!

I get "client denied by server configuration: proxy:http://site" errors - or a 403 Forbidden message

You have a <proxy:*> block that is denying your access. Check in mods-enabled/proxy.conf if you're on Debian or Ubuntu, because it defaults to denying all. As a quick test, you can comment out the whole section, but for prod env's it should be configured correctly.


Suppose I want to expose a website that is running on a non-standard port internally. I could use mod_proxy, if the website only used relative or path-only absolute URLS. However, the website happens to know what hostname and port it is supposed to be running on, and has some urls which are targetted directly at the hostname and port. mod_proxy will break in this case, because URLs in the webpages aren't rewritten, and I can't access the device directly from the external network.

mod_proxy_html solves this, by rewriting parts of the source code on the fly. It's implemented as a filter in apache2, which means all webpages in the appropriate block pass through it, and can be rewritten on the fly.

Here is an example config for exposing the CUPS web interface, which runs on port 631, via an ApacheReverseProxy:

First, get the mod_proxy_html module:

# apt-get install libapache2-mod-proxy-html

You may or may not have to enable the module with

# a2enmod proxy_html

Then edit the <IfModule mod_proxy.c> section of /etc/apache2/mods-enabled/proxy.conf

        <IfModule mod_proxy.c>
                ProxyRequests Off
                ProxyPass /cups
                ProxyHTMLURLMap /cups
                <Location /cups>
                        SetOutputFilter proxy-html
                        ProxyHTMLURLMap /               /cups/
                        ProxyHTMLURLMap /cups/          /cups/
        </IfModule mod_proxy.c>

Then reload the config

/etc/init.d/apache2 force-reload

New directives that are added include the ProxyHTMLURLMap directive, and the SetOutputFilter directive.

SetOutputFilter tells apache to pass the proxied content through the proxy-html filter, which mod_proxy_html provides. This does all the rewriting discussed below:

The first ProxyHTMLURLMap directive tells mod_proxy_html to rewrite any instance of "" to "/cups". This means any absolute URLs will be rewritten to point under the /cups/ Location, which will then get proxied appropriately.

The remaining ProxyHTMLURLMap directives handle URLs with just a set path, eg "/printers/printer1/". This will get rewritten to "/cups/printers/printer1/" and then proxied correctly. The last directive is a no-rewrite rule, intended to prevent infinite looping.

Using Apache 2 with Outlook Web Access (OWA)

First, enable some useful modules:

a2enmod proxy
a2enmod headers

Placeholder for when I actually get this going:

        DocumentRoot /var/www/html/exchange
        RedirectMatch ^/(index.html?)$
        RedirectMatch ^/exchange$

        # This secures the server from being used as a third party
        # proxy server
        ProxyRequests Off

        # Allows the proxying of a SSL connection
        SSLProxyEngine On
        ProxyVia On

        DocumentRoot /home/user/mail_proxy/html/
        RequestHeader set Front-End-Https "On"

        ServerName mail

        # Set up SSL to work with this host
        SSLEngine On
        SSLCertificateFile /etc/apache/webmail-proxy/server.crt
        SSLCertificateKeyFile /etc/apache/webmail-proxy/server.key

        SSLProxyMachineCertificateFile /etc/apache/webmail-proxy/certnew.cer

        ProxyPass /exchange/ https://mail-internal/exchange/
        ProxyPassReverse /exchange/ https://mail-internal/exchange/

        ProxyPass /exchweb/ https://mail-internal/exchweb/
        ProxyPassReverse /exchweb/ https://mail-internal/exchweb/

        ProxyPass /public/ https://mail-internal/public/
        ProxyPassReverse /public/ https://mail-internal/public/

        ProxyPreserveHost On

Here is a great article on Apache Proxying

Tested set of Apache reverse proxy rules

by Chris Covington -

How to ReverseProxy? Outlook Web Access (OWA) and Outlook Mobile Access (OMA) with Apache 2.X, mod_proxy and mod_rewrite

Add the following to your Apache 2.0+ httpd.conf/ssl.conf to use the ReverseProxy feature:

ProxyPreserveHost On

#OWA % character in email subject fix
RewriteEngine On
RewriteMap percentsubject int:escape
RewriteCond $1 ^/exchange/.*\%.*$
RewriteRule (/exchange/.*) ${percentsubject:$1} [P]

ProxyPass /exchange
ProxyPassReverse /exchange
ProxyPass /Exchange
ProxyPassReverse /Exchange
ProxyPass /exchweb
ProxyPassReverse /exchweb
ProxyPass /public
ProxyPassReverse /public
ProxyPass /iisadmpwd
ProxyPassReverse /iisadmpwd

ProxyPass /oma
ProxyPassReverse /oma

#ActiveSync (for WM5+ devices)
ProxyPass /Microsoft-Server-ActiveSync
ProxyPassReverse /Microsoft-Server-ActiveSync