Mango behind an Apache reverse proxy

Apache can easily be configured to proxy requests from a public facing HTTPS port to an private Mango instance behind your firewall. Some potential benefits include: ease of configuration and management of certificates for SSL/TLS, configurable content caching, request logging, rate limiting and protection against DDoS attacks.

Please see the following links for more information about reverse proxy servers -

Requirements and preliminary information

  • A basic understanding of the Apache web server

  • A SSL/TLS certificate as described in the SSL section

Install Apache

Head over to http://httpd.apache.org to install Apache on the public facing machine.

Configure your httpd.conf file

Enable required modules (Note the location of your modules may vary, these are for OSX’s default apache installation)

LoadModule proxy_module libexec/apache2/mod_proxy.so
LoadModule proxy_http_module libexec/apache2/mod_proxy_http.so
LoadModule proxy_connect_module libexec/apache2/mod_proxy_connect.so
LoadModule proxy_wstunnel_module libexec/apache2/mod_proxy_wstunnel.so
LoadModule rewrite_module libexec/apache2/mod_rewrite.so

Add the following virtual host section:

# Proxy from  public.example.com:443 to private Mango running on mango.example.com:8081
<VirtualHost *:443>
     ProxyPreserveHost Off
     ServerName public.example.com
     ServerAlias public.example.com
     ProxyRequests Off
     CustomLog "/var/log/apache-access-public-mango.log" common
     ErrorLog "/var/log/apache-error-public-mango.log"
     ProxyPass  /  http://mango.example.com:8081/
     ProxyPassReverse  /  http://mango.example.com:8081/
     ProxyPassReverseCookieDomain http://mango.example.com:8081 http://public.example.com:443

     #Specific for Mango 3.6.x only (Will cause 3.7.x websockets to break)
     RequestHeader set Host public.example.com
     RequestHeader set Origin https://public.example.com
     #End Specific for Mango 3.6.x

     #Rules for proxying WebSockets
     RewriteEngine On
     RewriteCond  %{HTTP:Upgrade} websocket [NoCase]
     RewriteCond %{HTTP:Connection} upgrade [NoCase]
     RewriteRule  /(.*) ws://public.example.com:443/$1 [Proxy,Last]

     SSLEngine On
     SSLProxyEngine On
     Include /etc/letsencrypt/options-ssl-apache.conf
     SSLCertificateFile /opt/ssl/sslPublic.pem
     SSLCertificateKeyFile /opt/ssl/sslPrivate.pem
</VirtualHost>

Understanding the configuration:

<VirtualHost *:443>

The virtual host defines the configuration for a specific port. Ensure that you have Listen 443 in your configuration if you want to listen on port 443.

ProxyPreserveHost Off

Proxy preserve host is disabled so that the Host: line from the incoming request is not passed to the proxied host, instead the hostname specified in the ProxyPass setting is used. https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypreservehost

ServerName public.example.com
ServerAlias public.example.com

The server name and alias should be the public facing server and will tell apache which virtual host to use for the request. https://httpd.apache.org/docs/2.4/mod/core.html#servername

ProxyRequests Off

Proxy requests allows or prevents Apache httpd from functioning as a forward proxy server. There are security concerns for this that can be reviewed here: https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxyrequests

#Specific for Mango 3.6.x only (Will cause 3.7.x web sockets to break)
RequestHeader set Host public.example.com
RequestHeader set Origin https://public.example.com

Setting the appropriate headers is very important for Mango 3.6.x to authenticate a request. In this example we set the Host and Origin to the public facing server before being passed on to Mango. Since there are security concerns with this Mango 3.7.+ does not accept this configuration. https://httpd.apache.org/docs/2.4/mod/mod_headers.html#requestheader

CustomLog "/var/log/apache-access-public-mango.log" common
ErrorLog "/var/log/apache-error-public-mango.log"

We define custom log files for this virtual host so we can review them more easily.

#Rules for proxying WebSockets
RewriteEngine On
RewriteCond  %{HTTP:Upgrade} websocket [NoCase]
RewriteRule  /(.*) ws://public.example.com:443/$1 [Proxy,Last]

Ensure that web socket requests are forwarded correctly by re-writing them for the internal server.

SSLEngine On
SSLProxyEngine On
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /opt/ssl/sslPublic.pem
SSLCertificateKeyFile /opt/ssl/sslPrivate.pem

Configure SSL for the proxy.

Configure Mango (3.7.0+)

Starting in Mango 3.7.0 you will also need to ensure that forwarding headers is enabled

web.forwardedHeaders.enabled=true

Also the IP address of the Proxy will need to be added to the list of trusted IPs (Note this is the IP not the hostname)

web.forwardedHeaders.trustedIpRanges=127.0.0.0/8,::1,proxy.ip.address