Introduction
It’s common practice to proxy to a group of webservers in a load-balanced production environment. And in such a setup, it’s also common to terminate SSL at the load-balancer. This has two advantages: firstly, it means only one SSL certificate installation is required; secondly, only the load-balancer needs to worry its pretty little head with decrypting incoming requests.
However this can have some disadvantages, chief of which is that any code that relies on the the HTTPS server variable, such as checks for IsSecureConnection will no longer work as it will never be set for the requests proxied to the actual web server node. This is because the web server nodes will only ever see HTTP traffic as SSL is being terminated at the load-balancer. I mean, duh. This is commonly worked around by setting a request header (eg SSL) at the load-balancer for any HTTPS traffic received there. The application’s code then checks for the presence of this header instead of the HTTPS server variable.
So What’s the Problem?
The problem is that load-balancing is often only done on production and some staging environments, depending on budget. Developer environments for example typically have a self-signed certificate bound directly to their local site. In this arrangement IsSecureConnection will function as expected. This is great, but it does leave a worrying gap between development and production environments as we now have to check one thing (IsSecureConnection) in some environments and another (our custom header, eg SSL) on production. This in itself wouldn’t be so bad if there was a way of replicating the SSL termination behaviour locally.
ARR Jim Lad
Application Request Routing to the rescue! Using this IIS7 feature and a couple of Url Rewrite rules we can create our own proxy with SSL termination and custom headers. Perhaps unsurprisingly, you’ll need Application Request Routing (ARR) and Url Rewrite installed to do this, so fire up Web Platform Installer and sort that out if you haven’t already.
ARR relies on the IIS default website to proxy requests through. This is whichever site has a wildcard host mapping. If you’ve deleted it for some reason, just create another site with a wildcard host mapping. You’ll also want a wildcard host mapping for HTTPS traffic on this site, as it will be the proxy for your actual application. Use the certificate from your application for this.
Your application presumably already has some bindings. Most likely one for HTTP and one for HTTPS, bound to your application’s host name. Delete the HTTPS binding. It is no longer required as all your application’s requests will be over HTTP once SSL termination is in place. You also need to change the HTTP host binding to something else. The actual name doesn’t matter, but for example if the host name was previously mywebsite, change it to something like mywebsiteterminated. Remember to add the new host name to your hosts file!
Configuring ARR
This part is quite easy. Open IIS Manager and click on the server root (typically the computer name). Under IIS, you should see the Application Request Routing icon:
Double click it. You will see what is most likely an empty table of Application Request Routing Cache information. Ignore it, and look at the Actions column on the right-hand side. Under Proxy is Server Proxy Settings. Click this to open them.
The important details here are:
- Enable proxy. Unsurprisingly (I hope!) this should be checked.
- Leave Use URL Rewrite to inspect incoming requests unchecked.
- Enable SSL offloading should be checked.
The final step is to add URL Rewrite rules to the proxy site. Since the proxy site exists solely to handle SSL offloading, its web.config will contain only the rewrite rules:
[html]
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Set header for HTTPS traffic" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="on" />
</conditions>
<serverVariables>
<set name="HTTP_SSL" value="true" />
</serverVariables>
<action type="Rewrite" url="http://mywebsiteterminated/{R:1}" />
</rule>
<rule name="HTTP traffic redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Rewrite" url="http://mywebsiteterminated/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
[/html]
As is hopefully clear from their names, these rules set a header servervariable and redirect to the actual website over HTTP. One point to note is that the servervariable is set to HTTP_SSL. There is a convention whereby header servervariables are prefixed with HTTP_. Including this in our rule ensures it can be accessed via the servervariables collection on the site proper.
Summary
You should now be able to replicate SSL offloading in your local environment. The key steps to this process are:
- Create a proxy website in IIS
- Configure ARR to use the proxy website
- Add rewrite rules to proxy site to add a custom header and redirect to the real website over HTTP
Leave a Reply