URL-адрес IIS10 Rewrite 2.1 проблема с двойным кодированием

У меня есть сервер IIS10 с ARR 3.0 и модулем перезаписи URL 2.1, который действует как обратный прокси-сервер для нескольких других веб-серверов. Другие серверы работают на разных портах, поэтому сервер IIS10 предоставляет «удобные URL-адреса» на порту 80. Перезапись URL-адресов используется для передачи запроса внутреннему серверу.

Одним из таких серверов является Jenkins.

У Jenkins есть предупреждающее сообщение, которое сообщает вам, правильно ли настроен обратный прокси-сервер (подробнее здесь), и это предупреждающее сообщение помогло мне найти проблему в обратном прокси-сервере.

Проблема в том, что URL Rewrite декодирует и кодирует мои URL-адреса таким образом, что к тому времени, когда они достигают Jenkins, они отличаются от того, что запросил браузер.

Пример:

Правило перезаписи URL:

<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>

При отправке следующего URL:

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 снова кодирует URL-адрес после моего Rewrite, что делает URL-адрес, полученный Jenkins, дважды закодированным:

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

Краткое резюме:

Когда вы смотрите на этот URL: /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> закодированы так, что Дженкинс может знать, что является частью path, а что <parameter1>.

Это означает, что когда URL Rewrite декодирует URL, <parameter1> смешивается с остальной частью path.

Желаемый результат — получить URL-адрес точно так, как его отправил браузер, но указывающий на локальный хост:

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

Есть ли способ отключить эти операции декодирования/кодирования, которые выполняет модуль перезаписи URL?

PS: я нашел сообщение в блоге о возможностях URL Rewrite v2.1. , и в нем говорится, что есть новый флаг, который можно использовать для отключения этого поведения, но я понятия не имею, как и где его установить.

В версиях URL Rewrite до v7.1.1980 при попытке использовать UNENCODED_URL URL Rewrite закодирует его, что может привести к двойному кодированию, если исходный URL уже был закодирован. Это нарушает раздел 2.4 RFC3986, в котором говорится: «Реализации должны не использовать процентное кодирование или декодирование одной и той же строки более одного раза, так как декодирование уже декодированной строки может привести к неправильной интерпретации октета данных процента как начала процентного кодирования или наоборот, в случае процентного кодирования уже процентного кодирования. закодированная строка». Это также сделало использование UNENCODED_URL непрактичным, особенно в сценариях обратной пересылки с ARR, когда внутренние серверы ожидают, что URL-адрес будет передан без изменений.

В версии 7.1.1980 мы добавляем флаг функции useOriginalURLEncoding, который позволяет отключить это несовместимое кодирование URL, если установлено значение true. Поведение по умолчанию останется неизменным (useOriginalURLEncoding по умолчанию имеет значение true).

Кто-нибудь здесь знает, как это сделать?


person Jorge Martins    schedule 06.11.2017    source источник


Ответы (2)


Мне удалось решить проблему, установив useOriginalURLEncoding = false, описанный в сообщении, на которое я ссылался в вопросе.

Чтобы установить флаг IIS Manager, выберите Configuration Editor и перейдите в раздел system.webServer/rewrite/rules, где вы найдете флаг useOriginalURLEncoding.

Установите флаг в false, и URL Rewrite больше не будет кодировать URL-адреса при использовании переменной {UNENCODED_URL} в правилах.

person Jorge Martins    schedule 07.11.2017
comment
Ты заслужил статую! Я часами искал решение для этого. Большое тебе спасибо! - person Floris Devreese; 15.01.2019

Вы можете добиться этого с помощью функции 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>
person Victor Leontyev    schedule 07.11.2017
comment
Это не работает, потому что символы косой черты, которые были закодированы ранее, не будут закодированы. Если вы внимательно посмотрите на URL-адрес запроса, вы заметите, что последняя часть: /https%3A%2F%2Fjenkins.mydomain%2Fmanage%3F где: %2F = / - person Jorge Martins; 07.11.2017
comment
Хм, я не могу найти никакой разницы. Не могли бы вы попробовать изменить Rewrite слово на Redirect и сравнить этот результат с проблемой / - person Victor Leontyev; 07.11.2017
comment
У перенаправления та же проблема, что и раньше. Я отредактировал вопрос. Настоящая проблема заключается в том, что закодированные символы косой черты принадлежат параметру, а не странице в Jenkins. - person Jorge Martins; 07.11.2017
comment
Хорошо, может быть, также лучше включить в свой вопрос ожидаемый результат. Чего вы хотите достичь - person Victor Leontyev; 07.11.2017
comment
Цель состоит в том, чтобы получить точно такой же URL-адрес, который отправил браузер, но указывающий на localhost:8080. Я только что обновил вопрос с этой информацией. - person Jorge Martins; 07.11.2017
comment
Я нашел еще одно альтернативное решение. Пожалуйста, проверьте мой ответ. Но твой лучше - person Victor Leontyev; 07.11.2017