I have been trying solutions for 6 hours to get this right but cannot find anything on either stack or microsoft's dev blogs. I am trying to force an HTTPS redirect from all external calls to my website while still going to the HTTP site when the website is accessed via an internal call, in this case by use of the IP address 192.168.8.68 in the URL bar of the browser. This worked perfectly until we installed an SSL certificate yesterday and implemented the following redirect rule:
<rule name="Redirect to HTTPS" patternSyntax="Wildcard" stopProcessing="true">
<match url="*" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTPS}" pattern="OFF" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" appendQueryString="false" />
</rule>
What I would like to know is, how would i bypass this if the incoming IP Address has the form 192.168.8.*? Adding specific iPs in regex causes the website to fail to load with a "Too many redirects error". I have already looked at the following list of questions in an attempt to solve this problem:
https://forums.iis.net/t/1166994.aspx?Rewrite+Redirection+for+only+external+users
IIS 7.5 redirect certain requests to other server using ip address
IIS | Block page specific url except for specific internal IP address
https://docs.secureauth.com/display/KBA/Use+URL+Rewrite+for+IP+Restrictions
Two instances of the same Website on IIS with different web.config (two different databases)
Single Website Directory / Multiple IIS Websites (Multiple web.config files)
You could use this rule to bypass the request from ip 192.168.8.*.
<rule name="Redirect to HTTPS" enabled="true" patternSyntax="ECMAScript" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTPS}" pattern="OFF" />
<add input="{REMOTE_ADDR}" pattern="192\.168\.8\.[0-9]+" negate="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" appendQueryString="false" redirectType="Permanent" />
</rule>
Related
I'm using URL Rewrite on IIS 10.0 and have the following rule configured at the server level (applicationHost.config). I've tried it in my web.config to no avail as well.
<rewrite>
<globalRules>
<rule name="redirect">
<match url="/admin" />
<conditions>
<add input="{REMOTE_ADDR}" pattern="10.30.*.*" negate="true" />
</conditions>
<action type="Rewrite" url="/error" />
</rule>
</globalRules>
</rewrite>
Is there anything immediately obviously wrong here? I want any external traffic trying to hit /admin to get redirected to an error page, and only allow a single internal IP block to access it. Pulling my hair out over here.
You may need to install Application Request Routing, which is an extension to IIS and is available here: https://www.iis.net/downloads/microsoft/application-request-routing
There is a problem in match regexp. It shouldn't start with slash. Correct is ^admin (^ means start of url)
<rule name="redirect">
<match url="^admin" />
<conditions>
<add input="{REMOTE_ADDR}" pattern="10.30.*.*" negate="true" />
</conditions>
<action type="Rewrite" url="/error" />
</rule>
And i have couple of notes:
1) For IP validation better to have regexp like that: 10.30.[0-9]{1,3}.[0-9]{1,3} instead of 10.30.*.*
2) Depends on your load balancer and network infrastructure, but you might need to check {HTTP_X_Forwarded_For} header instead {REMOVE_ADDR}, because client's IP might be in different header
I have setup a website in IIS and this website has two applications (as shown in the snapshot below).
I have to enable https on the applications. I have installed the SSL certificate and setup the applications to use https instead of http. Now I want to implement autoredirect from http to https, ONLY for the test application (PersonalCornerTest).
I am using UrlRewrite using the below links as reference,
https://www.sslshopper.com/iis7-redirect-http-to-https.html (Method 1)
and
https://blogs.msdn.microsoft.com/kaushal/2013/05/22/http-to-https-redirects-on-iis-7-x-and-higher/ (Method 1)
I used the below setting in configuration file of the test application,
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
However, the issue is, after adding the below code, when user tries to access the test site using http in url, it automatically redirects to https, but to the non-test site (i.e. PersonalCorner) and not the test application, which is confusing.
Can anyone let me know what mistake I am doing in the above setting? I want to implement autoredirect only for the test application.
Answering my query myself!
The below configuration fixed the issue,
<rewrite>
<rules>
<rule name="Redirect to https" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" appendQueryString="false" />
</rule>
</rules>
</rewrite>
Reference: How to force HTTPS using a web.config file
I have application which I have hosted in IIS 7.0.
Where I have to make sure that it works only on HTTPS and not on HTTP
so I have included below rule in my root config.
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Found" />
</rule>
</rules>
</rewrite>
After adding this rule when i tried to access my application I get below error:
Page has resulted in too many redirects. Clearing your cookies for
this site or allowing third-party cookies may fix the problem. If not,
it is possibly a server configuration issue and not a problem with
your computer. Here are some suggestions: Reload this web page later.
Learn more about this problem.
We have our ASP.NET application hosted on AWS with Elastic Load Balancing, and the rule in the question with the accepted answer did not work for us, and kept causing infinite redirects.
This is the rule that finally worked for us:
<rewrite>
<rules>
<rule name="HTTPS Rule behind AWS Elastic Load Balancer Rule" stopProcessing="true">
<match url="^(.*)$" ignoreCase="false" />
<conditions>
<add input="{HTTP_X_FORWARDED_PROTO}" pattern="^http$" ignoreCase="false" />
</conditions>
<action type="Redirect" url="https://{SERVER_NAME}{URL}" redirectType="Found" />
</rule>
</rules>
</rewrite>
Put below input condition:
<add input="{HTTPS}" pattern="on" />
Instead of:
<add input="{HTTPS}" pattern="off" />
My case, I needed to put like this:
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" ignoreCase="false" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_X_FORWARDED_PROTO}" pattern="^http$" />
<add input="{HTTPS}" pattern="on" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Found" />
</rule>
</rules>
I also faced that problem. All requests to the server were HTTP.
In my case problem was that I use Cloudflare DNS.
There is SSL/TLS setting that by default SSL/TLS encryption mode is set to Flexible.
Make sure to change the mode to Full.
Also as was mentioned by SNag we had a site that is sitting behind an ELB on Amazon. Attempting to apply a rewrite rule without the following input header was causing infinite redirects. This appears to be a result of needing the input type being HTTP_X_FORWARDED_PROTO as in the following: <add input="{HTTP_X_FORWARDED_PROTO}" pattern="^http$" ignoreCase="false" />.
From AWS documentation "Your application or website can use the protocol stored in the X-Forwarded-Proto request header to render a response that redirects to the appropriate URL." We are using the ELB with DNS entries to forward to the server with the site on it.
For IIS 10 (Windows Server 2016) I have followed instructions from here which generate a slightly different XML configuration for the rewrite:
<rewrite>
<rules>
<rule name="HTTP 2 HTTPS" patternSyntax="Wildcard" stopProcessing="true">
<match url="*" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTPS}" pattern="off" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Found" />
</rule>
</rules>
</rewrite>
The pattern is off and the match is only *.
I am using Liquid Web Cloud Sites, and ran into the exact same issue.
I tried the solution here, but it didn't work for what I needed because of this condition:
<add input="{HTTPS}" pattern="off" />
As the OP has it, this means is, "match and implement this rule when HTTPS is off". And the accepted solution for this question just inverts this, and matches the rule when HTTPS is on. It solved the infinite loop issue, but only because my rule was incorrectly matched - I actually only want to change the request to HTTPS when HTTPS is off. Thus none of my HTTP requests were getting forwarded.
Interestingly, none of my HTTPS requests were getting forwarded either, and from this (and a few other tests I did) I determined that although the browser shows HTTPS, the server is treating it like an HTTP request. Thus the server always believes it is receiving an HTTP request, and always ignored the rule (which now specified only match requests where HTTPS is on - i.e. never).
Hours of research and tests later, I deduced that its a similar issue as described here, summarised here:
To reduce costs [many hosting providers install the] SSL certificate on the TMG Gateway and this gateway is simply rewriting the request to standard HTTP when passing it to the actual web server. So by the time the request hits IIS and your web application it is a standard plain HTTP request.
.
TLDR;
Eventually I spoke to the team at Liquid Web who pointed me in the direction of a help article buried in their own site which solved the issue. They suggested I use the following rewrite rule which fixed it:
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect to HTTPS" stopProcessing="true">
<match url=".*"/>
<conditions>
<add input="{HTTP_CLUSTER_HTTPS}" pattern="^on$" negate="true"/>
<add input="{HTTP_CLUSTER_HTTPS}" pattern=".+" negate="true"/>
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{SCRIPT_NAME}" redirectType="SeeOther"/>
</rule>
</rules>
</rewrite>
</system.webServer>
I hope this might work for others in a similar situation.
Original liquidweb help article
If you use cloudflare for SSL , put it on Full mode
Cloudflare -> SSL/TLS -> Overview -> Full
Figure
I figured out something regarding this issue. Basically, if the incoming request is HTTPS do nothing.
<rule name="No Redirect if https" enabled="true" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAny" trackAllCaptures="false">
<add input="{HTTPS}" pattern="^ON$" />
</conditions>
<action type="None" />
</rule>
<rule name="Redirect to https" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern="^\example\.com$" />
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{R:0}" />
</rule>
How do you use IIS's url rewrite module to force users to use ssl while you are behind an elastic beanstalk load balancer?
This is more difficult than it sounds for a few reasons. One, the load balancer is taking care of ssl so requests passed from the load balancer are never using ssl. If you use the traditional rewrite rule you will get an infinite loop of redirects. Another issue to contend with is that the AWS healthcheck will fail if it receives a redirect response.
The first step in the solution is to create a healthcheck.html page and set it in the root directory. It doesn't matter what the content is.
Set your load balancer to use the healthcheck.html file for health checks.
Add the rewrite rule below in your web.config's <system.webServer><rewrite><rules> section:
<rule name="Force Https" stopProcessing="true">
<match url="healthcheck.html" negate="true" />
<conditions>
<add input="{HTTP_X_FORWARDED_PROTO}" pattern="https" negate="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
</rule>
Notice that the rule match is on anything but our healthcheck file. This makes sure the load balancer's health check will succeed and not mistakenly drop our server from the load.
The load balancer passes the X-Forwarded-Proto value in the header which lets us know if the request was through https or not. Our rule triggers if that value is not https and returns a permanent redirect using https.
Firstly I want to thank Ross for his original answer, it set me on my way to building up an IIS URL Rewrite rule that worked for me by using my existing HTTP to HTTPS redirect rule that I used before my website was behind an AWS Elastic Load Balancer.
<rule name="Redirect to HTTPS" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_X_FORWARDED_PROTO}" pattern="https" negate="true" />
<add input="{REMOTE_HOST}" pattern="localhost" negate="true" />
<add input="{REMOTE_ADDR}" pattern="127.0.0.1" negate="true" />
<add input="{HTTP_HOST}" pattern="localhost" negate="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>
This rule allows you to access your site locally within Visual Studio or on the server on port 80 without having to access over HTTPS, so you only have to have a binding for port 80 on the server. It doesn't suffer from the things that others have mentioned (Duplicated querystring etc.).
I personally haven't had any issue with the health check, I didn't need to create a file on the server for the elastic load balancer to ping. I have my load balancer set to health check on TCP:80 and it works.
Luke's answer works perfect if you are using an ELB but will not work with an ALB. For an ALB Ross Pace answer is correct.
But you can also combine the two so that way you can access the site locally without being redirected to HTTPS.
<rule name="Redirect to HTTPS" enabled="true" stopProcessing="true">
<match url="healthcheck.html" negate="true" />
<conditions>
<add input="{HTTP_X_FORWARDED_PROTO}" pattern="https" negate="true"/>
<add input="{REMOTE_HOST}" pattern="localhost" negate="true"/>
<add input="{REMOTE_ADDR}" pattern="127.0.0.1" negate="true"/>
<add input="{HTTP_HOST}" pattern="localhost" negate="true"/>
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent"/>
</rule>
This worked for my application - IIS 8.5, redirect HTTP to HTTPS behind an AWS ALB. The key was adding appendQueryString="false" to prevent the query string duplication on redirect. You can add the traps for health check and localhost processing as needed. I did not need to add the health check trap, as we added this to the web.config of the app, making it app specific. Our health check is the default app on the domain, so it was not affected.
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect to HTTPS" enabled="true" stopProcessing="true">
<match url="^(.*)$" />
<conditions>
<add input="{HTTP_X_FORWARDED_PROTO}" pattern="https" negate="true"/>
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" appendQueryString="false" redirectType="Permanent"/>
</rule>
</rules>
</rewrite>
I have the following rule on the site to redirect http to https. We just found out though that our app got submitted with just an http for the api. Until we can get this updated I need the site to ignore calls to the /api folder and only redirect everything else. I'm sure there's a way to say something like if URL does not contain /api/ then redirect.
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>
Add an entry similar to <add input="{R:0}" pattern="/api(/|$)(.*)" negate="true" /> so that the whole file is:
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{R:0}" pattern="/api(/|$)(.*)" negate="true" />
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>
Example URL: http://site.com/api/function
So, if the URL after the site matches any of the following it will stop processing (and thus not push the user to https)
/api
/api/anything
Any https URL
We run into the same kind of thing with a large application run in IIS behind a reverse proxy. The URL rewrite addon for IIS (that you appear to be using) is a bit of a pain, but it does the job really well and tolerates the MVC framework.
As you mentioned, simply putting a rewrite block in an API directory won't work because with MVC there are no directories. You would think MS would have a better solution for this -- but they don't. It makes things all the more challenging.
If you place a separate Web.config file in the /api application or directory you can override whatever rules apply for the site as a whole.
Check out Tip #1 in this article, and if you have the time read them all:
http://weblogs.asp.net/jgalloway/archive/2012/01/17/10-things-asp-net-developers-should-know-about-web-config-inheritance-and-overrides.aspx
John Galloway's blog is a fantastic resource for all things IIS and ASP.NET.