IIS 7 - Restrict Application by IP Address behind load balancer

You can use the IIS URL Rewrite module to accomplish this.

Add a new inbound rule with conditions that check to see if the IP address does not match {HTTP_X_Forwarded_For}. You can then set the rule up to redirect, rewrite, or abort the request.

You can a new condition for each IP address you wish to white-list.


Using IIS URL Rewrite module to normalize REMOTE_ADDR and implement IP Restrictions.

With the following recipe REMOTE_ADDR will be set to the real Client-IP regardless if there is a trusted reverse proxy in front to set HTTP_X_FORWARDED_FOR. That means you can remove the reverse proxy from in front of IIS and these IP Restrictions will still continue to work as expected.

Normalize REMOTE_ADDR in applicationHost.config

Set this in the global IIS applicationHost.config:

<rewrite>
    <allowedServerVariables>
        <add name="REMOTE_ADDR" />
        <add name="REMOTE_HOST" />
    </allowedServerVariables>
    <globalRules>
        <rule name="Remote" patternSyntax="ECMAScript">
            <match url=".*" ignoreCase="false" />
            <conditions>
                <add input="{REMOTE_ADDR}" pattern="^10\.1\.1\.[123]$" ignoreCase="false" />
                <add input="{HTTP_X_FORWARDED_FOR}" pattern="\d+\.\d+\.\d+\.\d+$" ignoreCase="false" />
            </conditions>
            <serverVariables>
                <set name="REMOTE_ADDR" value="{C:0}" />
                <set name="REMOTE_HOST" value="{C:0}" />
            </serverVariables>
            <action type="None" />
        </rule>
    </globalRules>
</rewrite>

The recipe above copies the last IP address it finds in HTTP_X_FORWARDED_FOR to the REMOTE_ADDR and REMOTE_HOST <serverVariables> only if the original value in REMOTE_ADDR matches the IP address of a trusted reverse proxy.

To have this recipe work, the first condition must be set to match your reverse proxy's IP address(es):

<add input="{REMOTE_ADDR}" pattern="^10\.1\.1\.[123]$" ignoreCase="false" />

In the example above, the client IP in HTTP_X_FORWARDED_FOR is trusted only if set by a reverse proxy at one of these IP addresses:

10.1.1.1 or 10.1.1.2 or 10.1.1.3

That takes care of setting REMOTE_ADDR to the real Client-IP.

IP Restrictions in web.config

IP Restrictions can be set with the IIS URL Rewrite module in a site's web.config using this recipe:

<system.webServer>
    <rewrite>
        <rules>
            <rule name="IP Restricted" patternSyntax="ECMAScript" stopProcessing="true">
                <match url=".*" ignoreCase="false" />
                <conditions>
                    <add input="{REMOTE_ADDR}" pattern="^(127\.|10\.20\.74\.|10\.25\.182\.|10\.64\.105\.10)" ignoreCase="false" negate="true" />
                </conditions>
                <action type="Rewrite" url="/403.html" appendQueryString="false" logRewrittenUrl="true" />
            </rule>
        </rules>
    </rewrite>
</system.webServer>

Edit the pattern= to only match the IP addresses or blocks you need to let in.

Change the <action /> to whatever needed.

Because the web.config recipe above filters on the standard REMOTE_ADDR variable, it works with and without HTTP_X_FORWARDED_FOR. The recipe in applicationHost.config <rewrite> <globalRules> ensures that REMOTE_ADDR is always set to the real Client-IP for anything that might later reference REMOTE_ADDR.


IIS 7 and beyond include the Dynamic IP Restrictions module, which supports filtering client requests by their X-Forwarded-For header, which is added to a request when using an AWS load balancer:

Support for web servers behind a proxy - If your web server is behind a proxy, you can configure the module to use the client IP address from an X-Forwarded-For header.

You can enable Proxy Mode support by checking the "Proxy" checkbox in the module's configuration page, then write rules to allow/deny IPs/CIDR ranges via the module.