Rewriting HTTPS variable based on value of X-Forwarded-Proto

Question

Monday, May 9, 2011 6:26 PM

I have a web cluster sitting behind an F5 load balancer. The load balancer is doing SSL-offloading and inserts X-FORWARDED-PROTO into the headers. It sets the value to "http" or "https". I would like to use URL Rewrite to set the HTTPS value to "on" when X-FORWARDED-PROTO is "https". I tried setting this up, but my test page shows that the HTTPS value is not being set to "on". I know that the condition is working properly because when I set the action to "abort" I get a network error in my browser. Is there something wrong with my serverVariables command? My rule and test page are below.

Thanks.

 

Rewrite rule:

         <rewrite>
            <allowedServerVariables>
                <add name="HTTPS" />
                <add name="X-FORWARDED-PROTO" />
            </allowedServerVariables>
            <rewriteMaps>
            </rewriteMaps>
            <globalRules>
                <rule name="HTTPS ReWrite" stopProcessing="true">
                    <match url="(.*)" />
                    <serverVariables>
                        <set name="HTTPS" value="on" />
                    </serverVariables>
                    <action type="Rewrite" url="{R:1}" />
                    <conditions logicalGrouping="MatchAny">
                        <add input="{HTTP_X_FORWARDED_PROTO}" pattern="https" />
                    </conditions>
                </rule>
            </globalRules>
        </rewrite>

 

Test Page:

<%@page language="C#" %>
<%
    Response.Write("HTTPS - " + Request["HTTPS"].ToString() );
    %><br><%
    Response.Write("HTTP_X_FORWARDED_PROTO - " + Request["HTTP_X_FORWARDED_PROTO"].ToString() );
%>

All replies (4)

Thursday, May 26, 2011 10:34 AM

Hi

Did you get an answer to this as I'm interested in doing the same thing.

Regards, Iain


Thursday, May 26, 2011 11:40 AM

Hi rjordan (and Iain),

I tested with your example and it worked perfectly for me without any changes.  The only thing I did differently for testing is to add another rule to add the header, like F5 would have done.  So I believe that you already have everything correct.  My only guess is that the name of the header from F5 isn't exactly what is expected.

Here's a couple things you can do to test:

Drop a page on your server that lists all servervariables: http://weblogs.asp.net/owscott/archive/2010/03/09/viewing-all-server-variables-for-a-site.aspx.

See if the name of the variables make sense.

Here's what my full test looks like, including faking the F5 header:

 <rewrite>
  <allowedServerVariables>
    <add name="HTTPS" />
    <add name="X-FORWARDED-PROTO" />
  </allowedServerVariables>
  <rewriteMaps>
  </rewriteMaps>
  <globalRules>
     <clear />
     <rule name="add header">
           <match url=".*" />
           <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
           <serverVariables>
               <set name="HTTP_X_FORWARDED_PROTO" value="https" />
           </serverVariables>
           <action type="None" />
      </rule>
      <rule name="HTTPS ReWrite" stopProcessing="true">
           <match url="(.*)" />
           <serverVariables>
               <set name="HTTPS" value="on" />
           </serverVariables>
           <action type="Rewrite" url="{R:1}" />
           <conditions logicalGrouping="MatchAny">
                <add input="{HTTP_X_FORWARDED_PROTO}" pattern="https" />
           </conditions>
       </rule>
   </globalRules>
</rewrite>

And the list of all server variables should show if F5 sends a different header than this test.


Friday, June 3, 2011 11:18 AM

Hi,

 I have a similar issue with an SSL load balancer at our new hosting provider. We have never used an SSL load balancer before and it appears to get stuck in a loop when load balacning SSL. I have tried the following rewrite rules sperately as the hosting team were not sure what variable I should changin was called:

<rewrite>
<allowedServerVariables>
<add name="HTTPS" />
<add name="X-FORWARDED-PROTO" />
</allowedServerVariables>
<rewriteMaps>
</rewriteMaps>
<globalRules>
<rule name="HTTPS ReWrite"
stopProcessing="true">
<match url="(.*)" />
<serverVariables>
<set name="HTTPS" value="on" />
</serverVariables>
<action type="Rewrite" url="{R:1}" />
<conditions logicalGrouping="MatchAny">
<add input="{ X-FORWARDED-PROTO }"
pattern="https" />
</conditions>
</rule>
</globalRules>
</rewrite><?xml:namespace prefix = u5 /><u5:p></u5:p> <u5:p></u5:p>And also tried:<u5:p></u5:p> <u5:p></u5:p><rewrite>
<allowedServerVariables>
<add name="HTTPS" />
<add name="X-FORWARDED-PROTO" />
</allowedServerVariables>
<rewriteMaps>
</rewriteMaps>
<globalRules>
<rule name="HTTPS ReWrite"
stopProcessing="true">
<match url="(.*)" />
<serverVariables>
<set name="HTTPS" value="on" />
</serverVariables>
<action type="Rewrite" url="{R:1}" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_X_FORWARDED_PROTO}"
pattern="https" />
</conditions>
</rule>
</globalRules>
</rewrite><u5:p></u5:p>

Neither seemed to work. I am not an IIS guru so i am now really stuck. Why it is going into a loop I dont know. It's using SSL offloading on the load balancer and passing to port 80. The web app looks for server-port-secure so I am not sure If i should be changing a different variable?

 

any help from you guys would be great and sorry for hijacking the thread

 

Kind regards,

 

Paul


Friday, June 3, 2011 11:50 AM

Hey Paul,

First, make sure your SSL load balancer is actually inserting the X-FORWARDED-PROTO header. I imagine just about every dynamic language has a way to dump all the SERVER and HTTP variables. If you don't see it set, then check with your hosting provider or whoever manages the load balancer and ask them to insert a header such as X-FORWARDED-PROTO. Make sure the value is set based on the client request, http or https.

Once you confirm you have a specific header for this, then you should be able to use your rewrite rule and it should fix the loop. Keep in mind if your server has wildcard handlers, then you won't be able to rewrite HTTPS. Your developers will need to update their code to look at the new variable (if it exists). Here is an example with PHP:

     $HTTPSEnabled = (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) ?
        strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == "https":
        strtolower($_SERVER['HTTPS']) == "on";