Using Apache to proxy Virtual Radar Server

Virtual Radar Server is an open-source .NET application for tracking aircraft emitting Mode-S transmissions and ADS-B messages. It’s an ideal tool to display the output from your own receivers, or merge the outputs from different sources.

Here’s a quick guide to adding IPv6 and SSL/TLS support to VRS using an Apache reverse proxy. I am assuming a level of familiarity with Linux administration and Apache configuration.

Install apache

Instructions for distros vary, but for Debian/Ubuntu systems, apt will handle most of the dependencies for us.

apt-get install apache2

Enable necessary modules

We need mod_headers for HSTS support (strict transport security).

a2enmod headers proxy proxy_http proxy_html ssl

Get or generate SSL certificate

I’m using Let’s Encrypt in this example; other options include buying a commercial certificate, or generating your own using openssl.

Since Ubuntu doesn’t have a package for certbot (at least not until 16.10), it’ll need a manual install. Instructions here:

https://certbot.eff.org/all-instructions/#ubuntu-14-04-trusty-apache

Let’s Encrypt normally verifies you own the domain by checking for a hidden file in the webserver’s document root. Since we aren’t going to have a document root – we’re just proxying requests to VRS, we can use Let’s Encrypt’s rather hidden DNS authentication.

You will need to add a DNS TXT record to your domain’s DNS zone, so you’ll want to dig out the necessary settings for that first. Most domain registrars provide a login to a DNS management tool.

certbot certonly -m <your_email> –agree-tos –manual -d <your_domain> –preferred-challenges dns

Obviously substituting <your_email> and <your_domain> with your own details – remembering this is the fully-qualified domain name where your VRS install should be accessible, e.g. vrs.minotaur.cc.

If you’ve successfully acquired a certificate from Let’s Encrypt, you should find the following three files are now on your system:

/etc/letsencrypt/live/<your_domain>/cert.pem
/etc/letsencrypt/live/<your_domain>/privkey.pem
/etc/letsencrypt/live/<your_domain>/chain.pem

Configure apache vhosts

Assuming you’ve successfully acquired your SSL certificate, you can now create an apache vhost configuration for the VRS proxy.

Create the config in /etc/apache2/sites-available/

I’m assuming a filename of 001-vrs.conf to make sure we load after the default vhost.

Here’s my example:

<IfModule proxy_module>

<VirtualHost *:80>
        ServerName <your_vrs_domain>
        Redirect permanent / https://<your_vrs_domain>
</VirtualHost>

<IfModule ssl_module>
<VirtualHost *:443>
        ServerName <your_vrs_domain>
        ProxyPass "/" "http://localhost:8080/VirtualRadar/"
        ProxyPassReverse "/" "http://localhost:8080/VirtualRadar/"
        ProxyPassReverseCookieDomain "<your_fqdn>" "<your_vrs_domain"
        ProxyPassReverseCookiePath "/" "/VirtualRadar/"

        ErrorLog /var/log/apache2/vrs_error.log
        CustomLog /var/log/apache2/vrs_combined.log combined

        <IfModule log_config_module>
                TransferLog /var/log/apache2/vrs_access.log
        </IfModule>

        SSLEngine on

        SSLProtocol ALL -SSLv3 -TLSv1 -TLSv1.1
        SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
        SSLCompression Off
        SSLSessionTickets Off
        SSLHonorCipherOrder On

        # OCSP Stapling, only in httpd 2.3.3 and later
        SSLUseStapling On
        SSLStaplingResponderTimeout 5
        SSLStaplingReturnResponderErrors Off

        # HSTS (mod_headers is required) (15768000 seconds = 6 months)
        Header always set Strict-Transport-Security "max-age=15768000"

        SSLCertificateFile /etc/letsencrypt/live/<your_vrs_domain>/cert.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/<your_vrs_domain>/privkey.pem
        SSLCertificateChainFile /etc/letsencrypt/live/your_vrs_domain>/chain.pem

        ## SSL Protocol Adjustments
        <IfModule setenvif_module>
                BrowserMatch ".*MSIE.*" \
                        nokeepalive ssl-unclean-shutdown \
                        downgrade-1.0 force-response-1.0
        </IfModule>

        ## Per-Server Logging:
        # The home of a custom SSL log file. Use this when you want a compact
        # non-error SSL logfile on a virtual host basis.
        <IfModule log_config_module>
                CustomLog /var/log/apache2/vrs_request.log \
                        "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
        </IfModule>
</VirtualHost>
</IfModule>
</IfModule><br>

Let’s go through the vhost configuration and see what each bit does.

<VirtualHost *:80>
        ServerName <your_vrs_domain>
        Redirect permanent / https://<your_vrs_domain>
</VirtualHost>

This basic vhost container forces any non-SSL requests to be redirected to the SSL-only vhost, thus preventing unencrypted connections to your VRS instance.

Substitute the domain you want to host VRS into <your_vrs_domain>, e.g. vrs.minotaur.cc

<VirtualHost *:443>
        ServerName <your_vrs_domain>
        ProxyPass "/" "http://localhost:8080/VirtualRadar/"
        ProxyPassReverse "/" "http://localhost:8080/VirtualRadar/"
        ProxyPassReverseCookieDomain "<your_fqdn>" "<your_vrs_domain"
        ProxyPassReverseCookiePath "/" "/VirtualRadar/"

This tells apache where to proxy requests to upstream, and how to rewrite responses coming back. As above, substitute the domain you want to host VRS into <your_vrs_domain>, e.g. vrs.minotaur.cc

If you’re running VRS on the same server, you can leave http://localhost:8080/VirtualRadar/ as-is. If not, modify accordingly to point to your actual VRS URL.

You’ll also need to substitute <your_fqdn> with the fully-qualified domain name of the server you’re running VRS on, if it’s different from the domain you want to use to access it. This rewrites VRS’ cookies so they contain the correct domain name and the browser can find them when you return to the site.

In my example, VRS runs on cronus.minotaur.cc, but I want VRS to be visible on vrs.minotaur.cc

SSLProtocol ALL -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256

Here we tell apache what sort of SSL/TLS connections we’re willing to accept. Many of the older SSL protocols have been found to be vulnerable, so we’ll exclude anything older than TLSv1.2.

Recommended SSL settings change frequently. This configuration was written in October 2016; the current recommended SSL settings can be found at https://cipherli.st and you can test your setup at https://www.ssllabs.com/ssltest

We’ll also set a sensible set of ciphers (in order of priority) so that modern browsers will connect using the most secure cipher possible, and outdated/vulnerable ciphers are excluded.

SSLCertificateFile /etc/letsencrypt/live/<your_vrs_domain>/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/<your_vrs_domain>/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/your_vrs_domain>/chain.pem

These tell apache where to find your SSL certificate, private key and any intermediate certificates. If you used Let’s Encrypt, just change <your_vrs_domain> to the domain you requested the certificate.

If you obtained your certificate by some other method, change the paths here to reflect where those certificates are located. It’s usually best to upload certs into /etc/ssl/ for ease of access.

Enable the new vhost

a2ensite vrs

Restart apache

service apache2 restart

You should now be able to access VRS securely by going to <your_vrs_domain> in a web browser. Check that automatic redirection worked by verifying the url now reads https://<your_vrs_domain>

For IPv6 access, simply add v6 configuration details to /etc/network/interfaces if you’ve not already done so – that’s beyond the scope of this document!