У меня есть сервер 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:
Я заметил, что закодированные символы декодируются перед запуском правила, поэтому {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).
Кто-нибудь здесь знает, как это сделать?