I am trying to restrict an application in IIS 7 by IP address on my web server behind a load balancer. The X-Forwarded-For header is set by the load balancer with the client's IP address.
What is the best way to extract that IP address in IIS 7 to setup IP address filtering on my application? If there is not a best way, I will end up using an HTTPModule to handle this for me.
Open the Internet Information Services (IIS) Manager. Highlight your server name, website, or folder path in the Connections pane, and then double-click IP Address and Domain Restrictions in the list of features. Click Edit Dynamic Restriction Settings in the Actions pane.
In the Web Server (IIS) pane, scroll to the Role Services section, and then click Add Role Services. On the Select Role Services page of the Add Role Services Wizard, select IP and Domain Restrictions, and then click Next. On the Confirm Installation Selections page, click Install. On the Results page, click Close.
In IIS Manager, expand SERVERNAME > Sites > click on a required website > double-click IP Address and Domain Restrictions (under IIS group). Click Add Allow Entry... (on the right pane) to add an IP address or IP address range which will be allowed to access the website. Click OK.
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.
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.
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.
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
.
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