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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With