I'm using IIS10 and URL-Rewrite and for some reason my website has a redirect-loop but ONLY on mobile devices. No matter which mobile, what network it's connected on or how many times I clear cache, the site won't load on any browser for any mobile device. I've tested using iphone, android, chrome, firefox, safari it's all the same.
Here are my rule(s) in the web.config
<rewrite>
<rules>
<rule name="CanonicalHostNameRule1">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^example\.com$" negate="true" />
<add input="{HTTP_HOST}" pattern="^(.*)\.example\.com$" negate="true" />
</conditions>
<action type="Redirect" url="http://example.com/{R:1}" />
</rule>
<rule name="Redirect to HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="SeeOther" />
</rule>
</rules>
</rewrite>
I have other websites hosted on the same machine with similar URL rewrite rules that work fine no problems.
Even with all my rules turned OFF, I'm still getting a redirect loop on mobile.
Any tools, tips/tricks on how to troubleshoot this would be most appreciated!
UPDATE: Info from Fiddler
RAW:
HTTP/1.1 301 Moved Permanently
Cache-Control: private
Content-Type: text/html; charset=utf-8
Location: http://example.com/
X-Redirect-Reason: Wrong Portal Alias Requested
Set-Cookie: dnn_IsMobile=True; path=/; HttpOnly
Set-Cookie: language=en-US; path=/; HttpOnly
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Date: Thu, 29 Oct 2020 13:19:56 GMT
Content-Length: 142
<html><head><title>Object moved</title></head><body>
<h2>Object moved to here.</h2>
</body></html>
Headers:
**Response Headers**
HTTP/1.1 301 Moved Permanently
**Cache**
Cache-Control: private
Date: Thu, 29 Oct 2020 13:19:56 GMT
**Cookies/Login**
Set-Cookie: dnn_IsMobile=True; path=/; HttpOnly
Set-Cookie: language=en-US; path=/; HttpOnly
**Entity**
Content-Length: 142
Content-Type: text/html; charset=utf-8
**Miscellaneous**
X-Redirect-Reason: Wrong Portal Alias Requested
**Security**
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
**Transport**
Location: http://example.com/
I see Wrong Portal Alias Requested but not sure what would cause that?
Credit to LexLi who got me looking in the right direction. Fiddler was very helpful.
Yes, the website is constructed on the DNN CMS application, the problem was that in DNN there is a table portalsettings that has a setting called DefaultPortalAlias there was a wrong value in this setting.
Additionally in DNN's PortalAlias table there are bit fields for IsPrimary and there the IsPrimary in my case was set to the www. version of the alias not the non-www. and in IIS my url rewrite canonical rule was point to the non-www. binding, this is what caused the loop. I'm not sure why it was only affecting mobile but it's working now after those changes.
Thanks #Lex Li for the insights!
Related
I followed this, which led to this to try to disable my website from accepting the TRACE method (verb). Basically I added the section below to <system.webServer> inside Web.config (Default Web Site and the other website):
<security>
<requestFiltering>
<verbs applyToWebDAV="false">
<add verb="TRACE" allowed="false" />
</verbs>
</requestFiltering>
</security>
It didnĀ“t work. Then I went to C:\Windows\System32\inetsrv\config\applicationHost.config and replaced all handlers' verb inside <handlers>. In a nutshell, all lines like this:
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
Became this:
<add name="StaticFile" path="*" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
I even restarted the server but when I check the available methods, TRACE is still there:
$ curl -I -X OPTIONS https://example.com/mysite
HTTP/1.1 200 OK
Allow: OPTIONS, TRACE, GET, HEAD, POST
Public: OPTIONS, TRACE, GET, HEAD, POST
X-XSS-Protection: 1; mode=block
Date: Thu, 07 Feb 2019 21:03:49 GMT
Content-Length: 0
So, how do I get rid of it?
To truly block TRACE requests, you should still keep a request filtering rule with TRACE verb blocked.
The curl command sends an OPTIONS request to IIS, and the ProtocolSupportModule generates the response message,
https://learn.microsoft.com/en-us/iis/get-started/introduction-to-iis/iis-modules-overview
However, Microsoft did not design any settings in system.webServer/httpProtocol section for you to change the value of the headers so as to hide TRACE from there.
But a workaround is to use URL Rewrite module,
https://blogs.msdn.microsoft.com/benjaminperkins/2012/11/02/change-or-modify-a-response-header-value-using-url-rewrite/
where you create two outbound rules for Allow and Public headers,
<rewrite>
<outboundRules>
<rule name="ChangeHeaders" stopProcessing="false">
<match serverVariable="RESPONSE_Allow" pattern="OPTIONS, TRACE, GET, HEAD, POST" />
<action type="Rewrite" value="OPTIONS, GET, HEAD, POST" />
</rule>
<rule name="Public">
<match serverVariable="RESPONSE_Public" pattern="OPTIONS, TRACE, GET, HEAD, POST" />
<action type="Rewrite" value="OPTIONS, GET, HEAD, POST" />
</rule>
</outboundRules>
</rewrite>
In my case works:
<requestFiltering>
<verbs allowUnlisted="false">
<clear/>
<add verb="GET" allowed="true" />
<add verb="HEAD" allowed="true" />
<add verb="POST" allowed="true" />
</verbs>
</requestFiltering>
Please notice that I don't allow OPTIONS.
When I not allow OPTIONS then TRACE was also not allowed.
I have a site for which I must force HTTPS everywhere.
I am concerned that in doing the HTTP to HTTPS redirect, if a user is already logged in (via cookies or tokens), that authentication information may be transferred inadvertedently in clear text.
How can I ensure that this does not happen?
One way to safely do a redirect without secure information being captured is with the rewrite engine - assuming you have no token/secure information in the URL itself (ie: session, etc).
<system.webServer>
<rewrite>
<rules>
<clear />
<rule name="HTTPS Redirect" 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="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
If you analyze the results of this configuration in Fiddler, you'll notice that the initial non-secured request has no secured information even if the user is authenticated.
Here is the GET request:
GET http://www.someurl.net/Dashboard HTTP/1.1
User-Agent: Fiddler
Host: www.someurl.net
The response is just a standard 301 perm redirect again with nothing secured transferred:
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Date: Mon, 08 Dec 2014 13:07:53 GMT
Location: https://www.someurl.net/Dashboard
Server: Microsoft-IIS/8.0
X-Powered-By: ASP.NET
Content-Length: 162
Connection: keep-alive
<head><title>Document Moved</title></head>
<body><h1>Object Moved</h1>This document may be found here</body>
i have tow websites e.g "testsite.ir" and "testsite.com". as i know my web site is on Windows Server 2008, Microsoft-IIS/7.5 .
how can i use 301 redirect to redirect users from .ir to .com?
can i use .htaccess file or i should use webconfig?
i use the code bellow in my webconfig, but nothing happen:
<rule name="Redirect from ir to com" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^www\.testsite\.ir$" />
</conditions>
<action type="Redirect" url="http://www.testsite.com/{R:0}" />
</rule>
Any help would be appreciated!
If you have remote access to the server you can do this within IIS. You need to enable HTTP Redirect within IIS (add/remove windows features) before you can add a rule. Once you've enabled it you can redirect the .ir site to the .com site. See here: http://www.iis.net/configreference/system.webserver/httpredirect
I need to write a URL Rewrite rule for my IIS 7.5 website that captures a value in a particular cookie, and then uses that value to construct a URL. For instance, the incoming requests looks like this:
GET http://myserver.com/test.aspx HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: en-US
User-Agent: Mozilla/5.0
Host: myserver.com
Cookie: foo=bar; bat=bar
I'd like to route them to this (based on the "foo" cookie value):
http://myserver.com/bar/test.aspx
fter reviewing the documentation and searching for examples, I'm stumped! Thanks for your help.
Answering my own question, here's a working example. The pattern may need additional work depending on what characters require supporting, but the following rule will will use the discovered cookie value and route to the discovered server--and the server can be specified by IPv4 address or by name (alphanumeric-and-period).
<rule name="Route Base On Cookie" stopProcessing="true">
<match url="^(.*)" />
<conditions>
<add input="{HTTP_COOKIE}" pattern="foo=(.*?);" />
</conditions>
<action type="Rewrite" url="http://{C:1}/{R:0}" />
</rule>
#Geoffrey To make your code support returning any cookie value, I'd recommend this pattern:
<add input="{HTTP_COOKIE}" pattern="foo=(.*?);" />
As a reminder, the {HTTP_COOKIE} value looks like this for example:
Cookie: foo=myexamplevalue; expires=Wed, 03-May-2014 22:31:08 GMT; path=/; HttpOnly\r\n
The following rule will use the discovered cookie value and route to the discovered path:
<rule name="Route Base On Cookie" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_COOKIE}" pattern="^(.+; )?foo=([^;]*)(;.+)?$" />
</conditions>
<action type="Rewrite" url="https://{HTTP_HOST}/{C:2}/{R:0}" />
</rule>
The pattern supports several cookies and doesn't depend on the order of foo in cookie (when it is the last, browser doesn't append ';'):
both foo=bar; bat=bar and bat=bar; foo=bar work fine.
It works correctly when you have another cookie with the same substring such as barfoo.
{C:2} corresponds to the second capture in cookie, i.e. value of foo in pattern="...";
{R:0} corresponds to whole url in <match url="...">. IIS uses path part only without host name, i.e. /test.aspx.
NB. It may be not secure to use value from cookie in path as is. Possibly you should match against the list of expected values (bar|bar2|bar3|bar4).
I have a very simple OutBound UrlRewriter rule that rewrites url's it finds in the body of the http response stream:
<rewrite>
<outboundRules>
<rule name="Scripted"
preCondition="IsHtml"
patternSyntax="ECMAScript"
stopProcessing="false">
<match filterByTags="None" pattern="http://someurl.com" />
<action type="Rewrite" value="http://anotherurl.com" />
</rule>
<preConditions>
<preCondition name="IsHtml" patternSyntax="Wildcard">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
The problem is that as soon as I turn on the preCondition no rewriting takes place.
I need to be able to use a pre-condition because the page is an ASP.NET page and uses ASP.NET script resources e.g. <script src="ScriptResource.axd?d=...." type="text/javascript" />.
By default script resources are gzip compressed and I want to keep them that way. Without the content type precondition the URL rewriter RewriteModule throws a 500.52 error - "Outbound rewrite rules cannot be applied when the content of the HTTP response is encoded ("gzip")."
Using Fiddler I can see that Content-Type: text/html; charset=utf-8 is being sent in the response header but UrlRwriter seems unable to match this.
Why is this happening?
This is because the Server Variable HTTP_ACCEPT_ENCODING is not added to the allowed server variables list. Add it there (you can google how to in IIS).