IIS10 URL重写2.1双重编码问题

时间:2017-11-06 21:22:30

标签: iis url-rewriting reverse-proxy url-rewrite-module iis-10

我有一台带有 ARR 3.0和URL重写模块2.1 的IIS10服务器,它充当其他几个Web服务器的反向代理。其他服务器在不同的端口上运行,因此IIS10服务器提供了友好的URL'在端口80上.URR重写用于将请求发送到后端服务器。

一个这样的服务器是Jenkins

Jenkins有一条警告消息,告诉您逆向代理是否配置良好(more details here),此警告消息帮助我在反向代理中发现问题。

问题在于,网址重写正在解码和编码我的网址,当他们到达詹金斯时,他们与浏览器请求的不同。

示例:

网址重写规则:

<rule name="Jenkins Rewrite" stopProcessing="true">
   <match url="(.*)" />
   <conditions>
     <add input="{HTTP_HOST}" pattern=".*jenkins.mydomain.*" />
     <add input="{HTTPS}" pattern="on" />
   </conditions>
   <action type="Rewrite" url="http://localhost:8080/{R:1}" appendQueryString="true" />
   <serverVariables>
     <set name="HTTP_X_FORWARDED_HOST" value="{HTTP_HOST}" />
     <set name="HTTP_X_FORWARDED_SCHEMA" value="https" />
     <set name="HTTP_X_FORWARDED_PROTO" value="https" />
   </serverVariables>
 </rule>

发送以下网址时

https://jenkins.mydomain/administrativeMonitor/hudson.diagnosis.ReverseProxySetupMonitor/testForReverseProxySetup/https%3A%2F%2Fjenkins.mydomain%2Fmanage%3F

我注意到编码的字符在触发规则之前被解码,使得{R:1}看起来像这样:     /administrativeMonitor/hudson.diagnosis.ReverseProxySetupMonitor/testForReverseProxySetup/https:/jenkins.mydomain/manage/

经过一些研究后我发现我可以使用 {UNENCODED_URL} 代替 {R:1} 来获取解码前的请求字符串,所以我调整了我的规则行动:

<action type="Rewrite" url="http://localhost:8080{UNENCODED_URL}" appendQueryString="false" />

不幸的是,URL Rewrite在我的Rewrite之后再次对URL进行编码,使得Jenkins收到的URL被双重编码:

/administrativeMonitor/hudson.diagnosis.ReverseProxySetupMonitor/testForReverseProxySetup/https%253A%252F%252Fjenkins.mydomain%252Fmanage%253F

简短摘要:

当您查看此网址时:  /administrativeMonitor/hudson.diagnosis.ReverseProxySetupMonitor/testForReverseProxySetup/https%3A%2F%2Fjenkins.mydomain%2Fmanage%3F

我们拥有的是: /administrativeMonitor/hudson.diagnosis.ReverseProxySetupMonitor/testForReverseProxySetup/<parameter1>

其中<parameter1> = https%3A%2F%2Fjenkins.mydomain%2Fmanage%3F

<parameter1>中的斜杠字符经过编码,以便Jenkins可以知道path的内容是什么,<parameter1>是什么。

这意味着,当网址重写解码网址时,<parameter1>会与path的其余部分混在一起。

所需的结果是获取与浏览器发送的URL完全相同但指向localhost的URL:

http://localhost:8080/administrativeMonitor/hudson.diagnosis.ReverseProxySetupMonitor/testForReverseProxySetup/https%3A%2F%2Fjenkins.mydomain%2Fmanage%3F

无论如何都要禁用URL Rewrite Module正在执行的解码/编码操作吗?

PS:我找到了一个关于URL Rewrite v2.1功能的blog post,它说有一个新的标志可用于禁用此行为,但我不清楚如何设置或在何处设置它

  

在v7.1.1980之前的URL重写版本中,当尝试使用时   UNENCODED_URL,URL Rewrite将对其进行编码,这可能导致双倍   编码如果原始URL已被编码这是违反的   RFC3986的2.4节,其中说&#34;实现不得   对数字进行百分比编码或解码不止一次,作为解码   已解码的字符串可能会导致错误解释百分比数据   八位字节作为百分比编码的开头,反之亦然   百分比编码已经百分比编码的字符串的情况。&#34;它也是   使用UNENCODED_URL是不切实际的,特别是反过来   具有ARR的转发器方案,后端服务器期望URL   没有修改地通过。

     

在v7.1.1980中,我们添加了一个功能标志useOriginalURLEncoding   允许您在设置时关闭此不合规的URL编码   为真。默认行为将保持不变   (默认情况下,useOriginalURLEncoding为true。)

这里有没有人知道怎么做?

2 个答案:

答案 0 :(得分:1)

我设法通过设置问题中引用的帖子中描述的useOriginalURLEncoding = false来解决问题。

要将标记设置为IIS Manager,然后选择Configuration Editor并转到system.webServer/rewrite/rules部分,您会在其中找到useOriginalURLEncoding标记。

将标志设置为false,并且在规则中使用{UNENCODED_URL}变量时,URL Rewrite将不再对URL进行编码。

答案 1 :(得分:0)

您可以使用UrlEncode功能实现此目的。将您的规则更改为:

<action type="Rewrite" url="http://localhost:8080/{UrlEncode:{R:1}}" appendQueryString="true" />

<强>更新: 另一种解决问题的方法

<rule name="Jenkins Rewrite" stopProcessing="true">
   <match url="(.*)" />
   <conditions>
        <add input="{UNENCODED_URL}" pattern="(.*)" />
         <add input="{HTTP_HOST}" pattern=".*jenkins.mydomain.*" />
         <add input="{HTTPS}" pattern="on" />
    </conditions>
    <action type="Rewrite" url="http://localhost:8080{C:1}" appendQueryString="true" />
   <serverVariables>
     <set name="HTTP_X_FORWARDED_HOST" value="{HTTP_HOST}" />
     <set name="HTTP_X_FORWARDED_SCHEMA" value="https" />
     <set name="HTTP_X_FORWARDED_PROTO" value="https" />
   </serverVariables>
 </rule>