Apache Tutorial: Reverse Proxies

When designing my development environment, I needed to make sure that I could have access to it from almost any external environment. I’ve had to work on customer sites in the past that have all non standard ports locked down. This means that access into my VPN and remote desktop connections would be blocked in such instances, or even http access to services I have running from home on non standard ports (eg Confluence uses port 8090 out of the box). The way around this was to use reverse proxies.

A reverse proxy appears to the client just like an ordinary web server. The client makes requests for content, and then the reverse proxy decides where to send those requests, and returns the content as if it was the source. In essence, it is a load balancer that channels requests between the calling client, and the server and port dictated by the client call.

I decided on using Apache as my web server, and set virtual hosts to proxy the calls to the other servers. After installing Apache, I needed to enable two modules: proxy_http and rewrite:

sudo a2enmod proxy_http
sudo a2enmod rewrite

Proxy_http (or mod_proxy) enables the use of the reverse proxy capabilities, while rewrite allows URL rewriting. The rewrite module is not specifically needed for a reverse proxy, but I do use it to secure my traffic – more on this further down.

The proxy directives that are of interest are:

ProxyRequests – This allows or prevents Apache from functioning as a forward proxy server.
ProxyPreserveHost – This option will pass the Host: line from the incoming request to the proxied host, instead of the hostname specified in the ProxyPass line.
ProxyPass – Allows remote servers to be mapped into the space of the local server.
ProxyPassReverse – Lets Apache adjust the URL in the Location, Content-Location and URI headers on HTTP redirect responses. This is essential when Apache is used as a reverse proxy (or gateway) to avoid by-passing the reverse proxy because of HTTP redirects on the backend servers which stay behind the reverse proxy.

Because I am using standard ports to connect to my server from within other networks, I also wanted to make sure the traffic I was sending was encrypted. This is where the rewrite module comes in – it allows me to force a redirect of traffic from port 80 to 443.

So my final virtual host configuration became the following:

<VirtualHost *:80>
  ServerName something.mysite.com
  RewriteEngine on
  ReWriteCond %{SERVER_PORT} !^443$
  RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R,L]
  ErrorLog /var/log/apache2/something.mysite.com_error.log
  CustomLog /var/log/apache2/something.mysite.com_access.log common
<VirtualHost>

<VirtualHost *:443>
  ServerName something.mysite.com
  SSLEngine on
  SSLCertificateFile /etc/apache2/ssl/apache.crt
  SSLCertificateKeyFile /etc/apache2/ssl/apache.key
  ProxyRequests Off
  ProxyPreserveHost On
  ProxyPass / http://123.456.789.012:1234/
  ProxyPassReverse / http://123.456.789.012:1234/
  ErrorLog /var/log/apache2/something.mysite.com_error.log
  CustomLog /var/log/apache2/something.mysite.com_access.log common
<VirtualHost>

The first VirtualHost directive catches any traffic to something.mysite.com on port 80, and uses the rewrite module to redirect it to port 443. The second VirtualHost catches any traffic to something.mysite.com on port 443, uses my SSL certificate, and then forwards the traffic to the server of my choice (in this case my server at 123.456.789.012 on port 1234).

This way, I’m able to use standard web ports to access my severs in a secured way in an environment which may be otherwise restricted.

This entry was posted in Apache, Tutorials and tagged , , , , , , , . Bookmark the permalink.

4 Responses to Apache Tutorial: Reverse Proxies

  1. Pingback: Confluence Gotchya: Resolving Images After Site Move | Code Monkey

  2. Jeremy Thacker says:

    I realize this is an older post but I’m trying to accomplish the same type of setup on my home network. I’ve got several machines running behind a DD-WRT router and some of those machines are running multiple servers. In addition, I own my own domain (example.com). On my primary machine, I’ve got WAMP setup and several other servers (SABnzbd, Sickbeard, CouchPotato, etc) on multiple ports. I’ve, also, got a RaspberryPi running Home-Assistant that I’d like to access remotely. My end goal is to use Let’s Encrypt to encrypt all of my traffic on my network but I’m unsure of how to do that. In addition, I’d like to be able to use subdomains to access each server from inside or outside of my network (sab.example.com, couch.example.com). Could you explain how you configured your SSL encryption to work for the entire network? My understanding is that Let’s Encrypt doesn’t allow the use of wildcards currently.

    • Kristian says:

      Hi Jeremy,

      I’ve not used Let’s Encrypt, but it looks interesting and I might try it out. My certificates were self signed (and after a quick check expired as well), and therefore I get warnings for all of my servers, but since these are not designed to be public facing that’s not an issue for me. I can’t recall if I used wild cards in my certs or not, but I think I’ll revisit my set up soon…

  3. Pingback: Apache Tutorial: Reverse Proxies | ly2xxx

Add a comment...

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s