Reverse Proxying Facebook
Tags: urlrewriting, javascript, iis
Published: 2020-08-19 14:10:32

Every time I figure out how to do something new, my manager comes along and starts "kicking out the tent walls a bit further." That happened today with me demonstrating a reverse proxying technique using IIS. No sooner had I demonstrated it working with one client, and almost working with another, that he asked, "Can we reverse proxy a Facebook site?"

So we wound up another subdomain on our server and pointed it at `https://www.facebook.com` using the following `web.config`. (Redacted slightly for security's sake.):
```xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="ReverseProxyInboundRule1" stopProcessing="true">
          <match url="(.*)" />
          <action type="Rewrite" url="https://www.facebook.com/{R:1}" />
          <serverVariables>
            <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
            <set name="HTTP_ACCEPT_ENCODING" value="" />
          </serverVariables>
        </rule>
        <rule name="Capture Http Origin Header">
          <match url=".*" />
          <conditions>
            <add input="{HTTP_ORIGIN}" pattern=".+" />
          </conditions>
          <serverVariables>
            <set name="HTTP_X_HTTP_ORIGIN" value="{C:0}" />
          </serverVariables>
          <action type="None" />
        </rule>
      </rules>
      <outboundRules>
        <rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1">
          <match filterByTags="A, Form, Img" pattern="^http(s)?://facebook.com/(.*)" />
          <action type="Rewrite" value="http{R:1}://sub.domain.com.au/{R:2}" />
        </rule>
        <rule name="Rewrite X-Frame-Options" enabled="true" patternSyntax="Wildcard">
          <match serverVariable="RESPONSE_X-Frame-Options" pattern="*" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="true" />
          <action type="Rewrite" />
        </rule>
        <rule name="Set-Access-Control-Allow-Origin for known origins" enabled="true">
          <match serverVariable="RESPONSE_Access-Control-Allow-Origin" pattern=".+" negate="true" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="true" />
          <action type="Rewrite" value="{HTTP_X_HTTP_ORIGIN}" />
        </rule>
        <rule name="Restore Accept Encoding" preCondition="Needs to Restore Original Accept Encoding" enabled="true">
          <match serverVariable="HTTP_ACCEPT_ENCODING" pattern="^(.*)$" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="true" />
          <action type="Rewrite" value="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" />
        </rule>
        <preConditions>
          <preCondition name="ResponseIsHtml1">
            <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
          </preCondition>
          <preCondition name="Needs to Restore Original Accept Encoding">
            <add input="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" pattern=".*" />
          </preCondition>
        </preConditions>
      </outboundRules>
    </rewrite>
  </system.webServer>
</configuration>
```
Now I can have an html file with an `iframe` in it with an `src` of "https://sub.domain.com.au/someFacebookSite" and have Facebook at that site appear in the iframe without the usual CORS-related notifications.

It's certainly not perfect and the manager, after an initial whoop of delight, is now not so happy. And why? Because the site in the iframe doesn't pick up the Facebook login details from any of the other browser windows. 

So now I have to figure out if that is even possible. 

Clues anyone?