IIS Rewrite Module: Change set-cookie path rule - iis

I am modifying my tor reverse proxy in IIS so that it must be accessed through a php page in my cgi-bin.
Here's where I'm stuck: I need to change the path value of all cookies set by the reverse proxy.
Example:
I request /cgi-bin/tor.php?url=easycoinsayj7p5l.onion/register.php in my browser. A backend local request is made to /tor/easycoinsayj7p5l.onion/register.php. A php session cookie is set with the path=/tor/easycoinsayj7p5l.onion/. This cookie does not set properly because the request is being made by /cgi-bin/tor.php. The path needs to be changed to /cgi-bin/ so the cookie can be set and accessed.
Below is the rule I've come up with to change this in the outbound requests section, however, it doesnt seem to do anything.
<rule name="rewritecookiepath" preCondition="" enabled="true">
<match serverVariable="RESPONSE_Set_Cookie" pattern="(.*)(Path=(.*); )(.*)" />
<conditions logicalGrouping="MatchAny" trackAllCaptures="true">
<add input="{URL}" pattern="(.*)" />
</conditions>
<action type="Rewrite" value="{R:1} Path=/cgi-bin/; {R:4}" />
</rule>
Please advise me what I'm missing!
-Thanks

The rule works fine on my side.
So please enable failed request tracing and it will show the root cause. I asssume there was something wrong with the value of Set-Cookie header.
https://learn.microsoft.com/en-us/iis/extensions/url-rewrite-module/using-failed-request-tracing-to-trace-rewrite-rules#:~:text=If%20the%20Failed%20Request%20Tracing,module%20installer%20in%20repair%20mode.

Related

Unable to remove server header details with URLRewrite in IIS 8.5

I have two queries regarding URLRewrite module.
To remove server information from header I had installed URLRewrite module in IIS8.5 and added changes in web.config.
<outboundRules rewriteBeforeCache="true">
<rule name="Remove Server header">
<match serverVariable="RESPONSE_Server" pattern=".+" />
<action type="Rewrite" value="" />
</rule>
</outboundRules>
</rewrite>
but I am still able to see server details. Do I need to configure these values in IIS to work?
Also, can URLRewrite cause delay in response time?
1.I tested your outboundRules and it works normally on my side. did you add RESPONSE_Server to Server Variables? If not, please add it.
2.URL Rewrite will cause delay in response time, but usually it can be ignored.

Change Host Header with IIS URLRewrite

I have requests coming to my webserver at
http://www.example.com/blog
I want to Rewrite that to another server listening on
http://blog.example.com
Here is my rewrite rule:
<rule name="blogredirect1" stopProcessing="true">
<match url="^blog(.*)" />
<action type="Rewrite" url="http://blog.example.com{R:1}" />
</rule>
What ends up happening is the rewrite sends the request to the second servers IP at blog.mysite.com but the request header's host is still www.mysite.com.
How do I make sure that the redirected request HOST is set to blog.mysite.com (which is set in the redirect rule)
May I know how did you check the HOST header?
It is recommended to check {HTTP_HOST} variable instead of view the HTTP header directly. Because if you view the request header, you will always see www.mysite.com.
You could fetch {HTTP_HOST} request variable from backend server blog.mysite.com.
However,If you means page in blog.mysite.com also displayed {HTTP_HOST} as www.mysite.com.Then please check whether you have set system.webServer/proxy/preserveHostHeader to true?
By the way, IIS support to rewrite HTTP_HOST manually, you could modify your rule like this:
<rule name="blogredirect1" stopProcessing="true">
<match url="^blog(.*)" />
<action type="Rewrite" url="http://blog.example.com{R:1}" />
<serverVariables>
<set name="HTTP_HOST" value="blog.example.com" />
</serverVariables>
</rule>
Please remember to Allow Server Variable{HTTP_HOST} in URL rewrite.
https://learn.microsoft.com/en-us/iis/extensions/url-rewrite-module/setting-http-request-headers-and-iis-server-variables
You could also set this in applicationhost.config <location path="sitename"> section.
<location path="Default Web Site">
<system.webServer>
<rewrite>
<allowedServerVariables>
<add name="HTTP_HOST" />
</allowedServerVariables>
</rewrite>
</system.webServer>
</location>

Access-Control-Allow-Origin issue with CORS and HTTPS redirect (IIS / IISNode / NodeJS)

I have a web application that is in two parts:
The "front-end" based in Angular (under Chrome) running on localhost:8000
The "back-end" based in ExpressJS/NodeJS, running on localhost:3000
In trying to gradually convert the application to entirely use HTTPS, I thought it would be better to convert the back-end, first. I have built it so that I can toggle the ability to enable/disable HTTPS on the back-end.
I have set up the back-end to run:
With two bindings under IIS: http and https
The NodeJS application under IISNode.
The problem comes about when I attempt to run the entire application (front- and back-end) under localhost in a local development environment, but with an HTTP-to-HTTPS rewrite (redirect) rule. After that I receive CORS errors on the front-end.
In short, in my local development environment, I am attempting:
After reading on all things CORS for hours, I adjusted the web.config and the applicationHost.config based upon this blog post and this StackOverflow article in an attempt to capture the Request Origin header value. Here is what they look like.
My applicationHost.config contains this section:
<location path="Default Web Site">
<system.webServer>
<rewrite>
<allowedServerVariables>
<add name="CAPTURED_ORIGIN" />
<add name="RESPONSE_Access-Control-Allow-Origin" />
</allowedServerVariables>
</rewrite>
</system.webServer>
</location>
And here is my Web.config:
<?xml version="1.0" encoding="utf-8"?>
<!--
This configuration file is required if iisnode is used to run node processes behind
IIS or IIS Express. For more information, visit:
https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config
-->
<configuration>
<system.webServer>
<handlers>
<!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
<add name="iisnode" path="bin/www" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="Capture Origin Header">
<match url=".*" />
<conditions>
<add input="{HTTP_ORIGIN}" pattern=".+" />
</conditions>
<serverVariables>
<set name="CAPTURED_ORIGIN" value="{C:0}" />
</serverVariables>
<action type="None" />
</rule>
<!-- HTTP-to-HTTPS redirect -->
<rule name="Redirect to HTTPS" enabled="true" stopProcessing="true">
<match url="(.*)" ignoreCase="true" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="true">
<add input="{HTTPS}" pattern="^off$" />
<add input="{HTTP_HOST}" pattern="([^/:]*?):[^/]*?" />
</conditions>
<action type="Redirect" url="https://{C:1}:3443/{R:0}" appendQueryString="true" redirectType="Temporary" />
</rule>
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}" />
</rule>
<!-- All other URLs are mapped to the node.js site entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True" />
</conditions>
<action type="Rewrite" url="bin/www" />
</rule>
</rules>
<outboundRules>
<rule name="Set-Access-Control-Allow-Origin for known origins">
<match serverVariable="RESPONSE_Access-Control-Allow-Origin" pattern=".+" negate="true" />
<action type="Rewrite" value="{CAPTURED_ORIGIN}" />
</rule>
</outboundRules>
</rewrite>
<!-- Make sure error responses are left untouched -->
<httpErrors existingResponse="PassThrough" />
</system.webServer>
<appSettings>
<add key="HTTPS_ENABLED" value="true" />
</appSettings>
</configuration>
The NodeJS application is also set up to handle CORS from localhost:8000, localhost:3000, localhost:3443 (local https), and "null" (converted to a string). (More on that, later.)
But if I use this configuration, then I get the following error in the front-end:
XMLHttpRequest cannot load
http://localhost:3000/foo/bar/
Response for preflight is invalid (redirect)
I suspect this is because IIS handled the redirect, but as a result it is handling the preflight check (HTTP OPTIONS) with an invalid response (redirect). However, according to this StackOverflow article, and the answer by #sideshowbarker, leads me to believe that the current version of Chrome, 59.0.3071.104, should be able to handle the HTTP redirect response from the CORS preflight OPTIONS request.
If I remove the server variables from the applicationHost.config and the HTTP-to-HTTPS rewrite and other rules and from the web.config, and then add code to allow the NodeJS application to handle the redirect to HTTPS, then the revised application looks like this:
Then it appears an unknown (NodeJS? IIS?) server error occurs because the request is cancelled:
You can see the cancellation in chrome://net-internals/#events even though the Origin in the request and the Access-Control-Allow-Origin in the response headers match:
There is no useful error message (even though one is being received by the client) which leads me to believe that it is IIS and not NodeJS that is cancelling the request and sending back no useful information.
I ended up adding a "null" entry to handle CORS when running under the NodeJS Lite Server (and not IIS as an experiment), but I need this to run under IIS/IISNode. However, there seems to be a problem with then IIS / IISNode / NodeJS combination.
I suspect that the Request Origin of "null" is most likely the result of a request, where the server performs a redirect, because you really have two requests:
- The original request from the browser
- The request that is the result of the redirect
When the redirect occurs, I am hypothesizing that the origin in the redirected request is not that same as the original URL, and for the reasons stated in https://www.w3.org/TR/cors/#generic-cross-origin-request-algorithms, the Origin request header within the redirect is null.
However, that doesn't explain, why, when I let NodeJS handle the redirect that the Origin request and the Access-Control-Allow-Origin response header values are both null and the request still gets cancelled. :-/
Finally, if I eliminate any attempt at HTTP-to-HTTPS redirect, then the application works without issue in my development environment.
The response to the preflight OPTIONS itself must always be a 2xx response—e.g., 200 or 204. The response to the preflight itself can never be a redirect—e.g., 302. The spec prohibits that.
But the response cited in the question shows a server responding with such a redirect; hence the error message cited. If a browser gets a 3xx response to a preflight OPTIONS request, the spec requires that the browser stop right there—to consider the preflight as failing.
So the only solution is to fix the server so it doesn’t give a redirect response for that OPTIONS.
There’s a different scenario with redirects and preflights that’s described in the question at CORS request with Preflight and redirect: disallowed. Workarounds?. In that scenario, this is what occurs:
OPTIONS /documents/123 --> 204 (everything okay, please proceed)
GET /documents/123 --> 303 redirect to `/documents/abc`
That is, the response to the OPTIONS request itself is a 2xx success, but the response to the subsequent actual request that the frontend code is sending is a 3xx.
For that case, the spec previously required browsers to stop and not allow the frontend code making the request to have access to the response, and browsers would respond with an error:
The request was redirected to 'http://localhost:3000/foo/bar/',
which is disallowed for cross-origin requests that require preflight.
Note that’s different than the error message cited for the scenario in the question, which is:
XMLHttpRequest cannot load http://localhost:3000/foo/bar/ Response
for preflight is invalid (redirect)
In that scenario (the one in the question), this is instead what occurs:
OPTIONS /documents/123 --> 307 redirect to `/documents/abc`
That is, the response to the OPTIONS is 3xx. The spec still requires a preflight failure for that.
But that other disallowed for cross-origin requests that require preflight case no longer requires failure, and that error should no longer occur in browsers; the spec changed in August 2016 to no longer require it, and all browser engines subsequently updated to match that change.
Chrome was the last browser to implement the update, but it was fixed in the Chrome sources in December 2016, and the fix shipped in Chrome 57.

IIS Reverse Proxy Re-Encoding URLs Containing Percent Sign (%)

I am trying to set up a reverse proxy for Jenkins using IIS 7.5, Application Request Routing 3.0 (ARR), and URL Rewrite 2.0.
I have the proxy mostly working, but am running into issues with URLs that contain the percent symbol (%).
No matter what I try, the proxy insists on either de-encoding or re-encoding the percent sign in the rewritten URL.
This is how I want the URLs rewritten:
http://my.proxy/a%2Fb -> http://my.host:8080/a%2Fb
This is how the URLs are actually being rewritten:
http://my.proxy/a%2Fb -> http://my.host:8080/a/b
- or -
http://my.proxy/a%2Fb -> http://my.host:8080/a%252Fb
How can I get IIS\ARR\Rewrite to stop re-encoding my rewritten URLs?
Things I've tried:
A normal reverse-proxy (rewrites the URL as http://my.host:8080/a/b):
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="(.*)" ignoreCase="true" />
<action type="Rewrite" url="http://my.host:8080/{R:1}" />
</rule>
Using the UNENCODED_URL server variable (rewrites the URL as http://my.host:8080/a%252Fb):
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="(.*)" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<add input="{UNENCODED_URL}" pattern="/(.*)" />
</conditions>
<action type="Rewrite" url="http://my.host:8080/{C:1}" />
</rule>
Just entering the URL in straight (as a test - also rewrites the URL as http://my.host:8080/a%252Fb):
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="(.*)" ignoreCase="false" />
<action type="Rewrite" url="http://my.host:8080/a%2Fb" />
</rule>
All the ideas in Scott Hanselman's excellent "Experiments in Wackiness: Allowing percents, angle-brackets, and other naughty things in the ASP.NET/IIS Request URL"
<httpRuntime requestValidationMode="2.0" requestPathInvalidCharacters="*,:,&,\" relaxedUrlToFileSystemMapping="true" />
<security>
<requestFiltering allowDoubleEscaping="true" />
</security>'
Note: I ran into this behavior when my IIS reverse proxy ran afoul of Jenkins' built-in reverse proxy checking system which attempts to do an HTTP redirect to a URL of this form.
Joseph, that is a great summary of all the ways I've tried to resolve the exact same issue, having IIS with SSL routing traffic to my Gerrit instance. When I found your post I hoped that maybe someone figured out a magic way to configure it but I guess it's not possible. I have tried one more thing, I've written a custom rewrite provider for IIS so that I can undecode the percent signs before routing is done, but then I realized that the encoding takes place later and this is pointless (I forgot about your step nr 3 that shows it very good).
I couldn't however get rid of IIS like out did, so I have figured a workaround. I have implemented a simple service that acts as additional proxy between IIS and Gerrit. When you configure IIS like in step 2, requests that are forwarded will get %25 in place of percent characters in the urls. Instead of reaching Gerrit, IIS forwards the requests to the proxy service. The service changes all occurrences of %25 to % (decodes percents) and forwards it to Gerrit. Nothing needs to be done with the response. For those who want to go this way you can start from my simple implementation of the proxy in C#:
https://gist.github.com/gralin/b5edfd908a41fc7268a7757698af1e66
I was able to fix this issue using the second approach and setting useOriginalURLEncoding="false":
<rules useOriginalURLEncoding="false">
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="(.*)" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<add input="{UNENCODED_URL}" pattern="/(.*)" />
</conditions>
<action type="Rewrite" url="http://my.host:8080/{C:1}" />
</rule>
</rules>
See also the official blog post for background information. The wording of useOriginalURLEncoding is a bit unfortunate.
I have thought using proxy with url contains % symbol has the problem, but after that i have found out it wasn't. The issue that the proxy URL too long.
I use datatable with option server-side: true and type: GET. Then when loading content from server with the proxy url too long, there is a problem. I have improve the size of url request and the issue has been fixed.
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxQueryString="4000" maxUrl="2000" />
</requestFiltering>
</security>
<rewrite>...</rewrite>
...
</system.webServer>
But keep in mind that allowing long query string and url is a security risk, more over, it’s a bad design.

Using URL Rewrite for Cross-Domain Http Requests

I am trying to write an inbound rewrite rule that basically captures all the requests to the root folder /api/*, and rewrite it to api.v2.movideo.com respecting the HTTP vs HTTPS traffic.
I followed the step by step instructions here: http://code.movideo.com/Setting_up_IIS7_to_use_URL_Rewrite_2.0_for_Cross-Domain_XMLHttpRequest_Calls
I installed Application Request Routing http://www.iis.net/expand/URLRewrite
Followed all the steps on that page, removed the instructed headers, did everything by the book, but all I get is this:
HTTP Error 500.50 - URL Rewrite Module Error.
There is a problem with the resource you are looking for, so it cannot be displayed.
When I change the rule from REWRITE to REDIRECT, it works fine, but it redirects, not rewrites! Ugh. What's going on here?
Here is my Rule:
<rule name="ReverseProxyInboundRule1" stopProcessing="false">
<match url="^api/(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{CACHE_URL}" pattern="^(https?)://" />
</conditions>
<action type="Rewrite" url="{C:1}://api.movideo.com/{R:1}" />
<serverVariables>
<set name="HTTP_ACCEPT_ENCODING" value="" />
</serverVariables>
</rule>
(2nd question: Are there any problems or things I should know installing Application Request Routing? It added a new 'Server Farms' section in my IIS, hmmmm...I have no idea what this is all about. )
If there are processing rules AFTER this rule, consider setting the stopProcessing attribute to true
Because you are using a serverVariables node, you must add the server variable to the allowedServerVariables collection for your server. Your can do this from using the IIS UI (details here: Setting HTTP request headers and IIS server variables) or from the command line:
%windir%\System32\inetsrv\appcmd.exe set config -section:system.webServer/rewrite/allowedServerVariables /+"[name='boo']" /commit:apphost

Resources