Mango behind an Apache reverse proxy

June 17th, 2020


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

Copyright © 2020 Radix IoT, LLC.