Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create redirect responses on IIS when running behind SSL-terminating reverse proxy?

I have an ASP.NET web site that normally runs on IIS over HTTPS. Now I want to put it behind a reverse proxy that will do SSL termination for me. The problem is that the request coming from the reverse proxy is on HTTP:80 and when I create a redirect response as per usual, the Location header of the response is set to http://... instead of https://...

I know that the reverse proxy passes X-Forwarded-Proto in the header and I can check for that header when creating redirect responses and redirect URL's in general. However, if possible, I'd like to avoid having to sprinkle checks for X-Forwarded-Whatever all around the code and have one more thing to think about when coding, and also have to double-check whether everything still works when it's deployed behind the proxy.

like image 496
Stefan Dragnev Avatar asked Nov 13 '14 09:11

Stefan Dragnev


1 Answers

The best way I've found is to use the IIS URL rewriting module and set the HTTPS and SERVER_PORT headers such that the proxied site doesn't even know it's working behind a proxy. I've used the following configuration in Web.config:

<rewrite>
    <allowedServerVariables>
        <add name="HTTPS" />
        <add name="SERVER_PORT" />
    </allowedServerVariables>
    <rules>
        <rule name="backend" patternSyntax="Wildcard">
            <match url="*" />
            <conditions>
                <add input="{HTTP_X_FORWARDED_PROTO}" pattern="https" />
            </conditions>
            <serverVariables>
                <set name="HTTPS" value="on" />
                <set name="SERVER_PORT" value="443" />
                </serverVariables>
            <action type="None" />
        </rule>
    </rules>
</rewrite>

The above section states that whenever an incoming request has X-Forwarded-Proto set to https, then it should set the server variables HTTPS and SERVER_PORT to mimick a request coming over HTTPS. Having this configuration I don't have to do any checks for X-Forwarded-Proto inside my own code.

Note that the URL Rewrite module is invoked towards the end of the pipeline and, notably, it runs after the HTTP Redirection module. If you redirect using this module or any other IIS-level mechanism, the constructed URL's will still have the wrong scheme. The fix for me so far was to re-implement all IIS-level redirects to use the URL rewrite module and nothing else.

Also note that normally the <allowedServerVariables> section cannot be set from application-level Web.config files. You will either need to unlock the section to be accessible to applications or you'll need to configure this section straight in the configuration of the root web site. Here's the script I use for installing and configuring URL rewriting on web nodes:

Param(
    [string] $package = 'rewrite_2.0_rtw_x64.msi'
)

Start-Process -Wait msiexec -ArgumentList @('/i', $package, '/quiet', '/qn', '/norestart')

$applicationHost = "C:\Windows\System32\inetsrv\config\applicationHost.config"

$config = [xml](Get-Content $applicationHost)

$webServer = $config.configuration.configSections.sectionGroup | where {$_.name -eq "system.webServer"}
$rewrite = $webServer.sectionGroup | where {$_.name -eq "rewrite"}
$serverVariables = $rewrite.section | where {$_.name -eq "allowedServerVariables"}
$serverVariables.SetAttribute("overrideModeDefault", "Allow")

$config.Save($applicationHost)
like image 172
Stefan Dragnev Avatar answered Nov 15 '22 05:11

Stefan Dragnev