Переопределение HTTP-заголовков и URL-адресов с помощью Шлюза приложений Azure

Шлюз приложений позволяет перезаписывать выделенное содержимое запросов и ответов. С помощью этой функции можно преобразовывать URL-адреса, параметры строки запроса, а также изменять заголовки запросов и ответов. Она также позволяет добавить условия для того, чтобы указанные заголовки перезаписывались только при соблюдении выбранных параметров. Эти условия основываются на сведениях о запросе и ответе.

Примечание.

Функции переопределения заголовка HTTP и URL-адреса доступны только для SKU шлюза приложений версии 2

Поддерживаемые типы перезаписи

Заголовки запросов и ответов

HTTP-заголовки позволяют клиенту и серверу передавать дополнительную информацию вместе с запросом или ответом. Переписывая эти заголовки, вы сможете выполнять важные задачи, такие как добавление полей заголовка, связанных с безопасностью (например, HSTS/X-XSS-Protection), удаление полей заголовка ответа, которые могут раскрывать конфиденциальную информацию, а также удаление сведений о портах заголовков типа "Х был перенаправлен на" (X-Forwarded-For).

Шлюз приложений позволяет добавлять, удалять или обновлять заголовки HTTP-запросов и ответов при перемещении пакетов запросов и ответов между клиентскими и внутренними пулами.

Дополнительные сведения о перезаписи заголовков запросов и ответов с помощью шлюза приложений через портал Azure см. здесь.

img

Поддерживаемые заголовки

Вы можете переписывать все заголовки в запросах и ответах, за исключением заголовков Соединения и Обновления. Шлюз приложений также можно использовать для создания пользовательских заголовков и их добавления к запросам и ответам, направляемым через сам шлюз.

URL-путь и строка запроса

Возможность повторного создания URL-адресов в шлюзе приложений позволяет:

  • Перезаписать имя узла, путь и строку запроса URL-адреса запроса

  • Выбрать перезапись URL-адреса всех запросов на прослушивателе или только тех запросов, которые соответствуют одному или нескольким заданным условиям. Эти условия основаны на свойствах запроса (переменные заголовка запроса и сервера).

  • Выбрать маршрутизацию запроса (с выбором внутреннего пула) на основе исходного URL-адреса или перезаписанного URL-адреса

Чтобы узнать, как переопределить URL-адрес с помощью шлюза приложений, используя портал Azure, см. необходимые сведения здесь.

Diagram that describes the process for rewriting a URL with Application Gateway.

Действия перезаписи

Используйте действия перезаписи для указания URL-адреса, заголовков запроса или заголовков ответа, которые требуется переопределить, и нового значения, в которое требуется совершить перезапись. Значение URL-адреса или нового или существующего заголовка может быть задано для следующих типов значений:

  • Текст
  • Заголовок запроса. Чтобы указать запрос заголовка, необходимо использовать синтаксис {http_req_headerName}
  • Заголовок ответа. Чтобы указать ответ заголовка, необходимо использовать синтаксис {http_resp_headerName}
  • Переменная сервера. Чтобы указать переменную сервера, необходимо использовать синтаксис {var_serverVariable}. См. список поддерживаемых серверных переменных
  • Сочетание текста, заголовка запроса, заголовка ответа и переменной сервера.

Условия перезаписи

Можно использовать условия перезаписи — дополнительную необязательную конфигурацию, — чтобы оценить содержимое запросов и ответов HTTP(S) и выполнить перезапись только при выполнении одного или нескольких условий. Шлюз приложений использует представленные ниже типы переменных для вычисления содержимого запросов и ответов:

  • HTTP-заголовки в запросе
  • HTTP-заголовки в ответе
  • Переменные сервера шлюза приложений

Можно использовать условие, чтобы определить, существует ли указанная переменная, соответствует ли она конкретному значению или же определенному шаблону.

Соответствие шаблону

Шлюз приложений использует регулярные выражения для сопоставления шаблонов в условии. При написании условий следует использовать совместимые выражения регулярного выражения 2 (RE2). Если вы используете Шлюз приложений Брандмауэр веб-приложений (WAF) с набором основных правил 3.1 или более ранней версии, при использовании perl-совместимых регулярных выражений (PCRE) при выполнении утверждений lookahead и lookbehind (отрицательных или положительных) может возникнуть проблема.

Захватываемая

Чтобы захватить подстроку для последующего использования, заключите в круглые скобки вложенный шаблон, совпадающий с подстройкой в регулярном выражении условия. Первая пара скобок хранит свою подстроку в 1, вторую пару в 2 и т. д. Вы можете использовать столько круглых скобок, сколько пожелаете. Perl просто будет определить больше числовых переменных для представления этих захваченных строк. Некоторые примеры из ссылки:

  • (\d) (\d) # Сопоставление двух цифр, захват их в группы 1 и 2

  • (\d+) # Сопоставление одной или нескольких цифр, захватив их в группу 1

  • (\d)+ # Сопоставление цифры один или несколько раз, захватив последний в группу 1

Примечание.

/ Использование префикса и суффикса шаблона не должно быть указано в шаблоне для сопоставления значений. Например, (\d)(\d) будет соответствовать двум цифрам. /(\d)(\d)/ не соответствует двум цифрам.

После захвата вы можете ссылаться на них в наборе действий, используя следующий формат:

  • Для захвата заголовка запроса необходимо использовать {http_req_headerName_groupNumber}. Например, {http_req_User-Agent_1} или {http_req_User-Agent_2}
  • Для захвата заголовка ответа необходимо использовать {http_req_headerName_groupNumber}. Например, {http_resp_Location_1} или {http_resp_Location_2}
  • Для серверной переменной необходимо использовать {var_serverVariableName_groupNumber}. Например, {var_uri_path_1} или {var_uri_path_2}

Примечание.

Случай переменной условия должен соответствовать регистру переменной записи. Например, если моя переменная условия — User-Agent, моя переменная записи должна быть для user-agent (т. е. {http_req_User-Agent_2}). Если переменная условия определена как пользователь-агент, переменная записи должна быть для агента пользователя (т. е. {http_req_user-agent_2}).

Если вы хотите использовать целое значение, не следует упоминать это число. Просто используйте формат {http_req_headerName} и т. д. без groupNumber.

Переменные сервера

Шлюз приложений использует переменные сервера для хранения полезной информации о сервере, подключении к клиенту и текущем запросе к соединению. Примеры хранимых сведений включают IP-адрес клиента и тип веб-браузера. Переменные сервера изменяются динамически, например при загрузке новой страницы или при публикации формы. Эти переменные можно использовать для вычисления условий перезаписи и перезаписи заголовков. Чтобы использовать значения переменных сервера для перезаписи заголовков, необходимо указать эти переменные в синтаксисе {var_serverVariableName}

Шлюз приложений поддерживает перечисленные ниже переменные сервера:

Имя переменной Description
add_x_forwarded_for_proxy Поле заголовка X-Forwarded-For в запросе клиента с переменной client_ip (см. описание далее в этой таблице) добавляется к ней в формате IP1, IP2, IP3 и т. д. Если в заголовке запроса клиента нет поля X-Forwarded-For, значение переменной add_x_forwarded_for_proxy будет равно значению переменной $client_ip. Эта переменная особенно полезна при необходимости перезаписи заголовка X-Forwarded-For, установленного шлюзом приложений, так, чтобы заголовок содержал только IP-адрес без сведений о порте.
ciphers_supported Возвращает список шифров, поддерживаемых клиентом.
ciphers_used Возвращает строку шифров, которая используется для установленного соединения TLS.
client_ip IP-адрес клиента, от которого шлюз приложений получил запрос. Если перед шлюзом приложений и исходным клиентом есть обратный прокси-сервер, client_ip вернет IP-адрес обратного прокси-сервера.
client_port Порт клиента.
client_tcp_rtt Сведения о TCP-подключении клиента. Доступно для систем, поддерживающих дополнительный сокет TCP_INFO.
client_user При использовании проверки подлинности HTTP эта переменная будет содержать имя пользователя, передаваемое для проверки подлинности.
host В следующем порядке значимости: имя узла из строки запроса, имя узла из поля "Host" в заголовке запроса или имя сервера, соответствующее запросу. Пример: в запросе http://contoso.com:8080/article.aspx?id=123&title=fabrikam значение узла будет равно contoso.com
cookie_name Имя файла cookie.
http_method Метод, используемый для выполнения запроса URL-адреса. Например, GET или POST.
http_status Статус сеанса. Например, 200, 400 или 403.
http_version Протокол запроса. Обычно это бывает HTTP/1.0, HTTP/1.1 или HTTP/2.0.
query_string Список пар "переменная-значение", которые следуют за "?" в запрошенном URL-адресе. Пример: в запросе http://contoso.com:8080/article.aspx?id=123&title=fabrikam query_string будет иметь значение id=123&title=fabrikam
received_bytes Длина запроса (включая строку запроса, заголовок и текст запроса).
request_query Аргументы в строке запроса.
request_scheme Схема запроса: HTTP или HTTPS.
request_uri Полный исходный код URI запроса (с аргументами). Пример: в запросе http://contoso.com:8080/article.aspx?id=123&title=fabrikam* request_uri будет иметь значение /article.aspx?id=123&title=fabrikam
sent_bytes Количество отправленных клиенту байтов.
server_port Порт сервера, принявшего запрос.
ssl_connection_protocol Протокол установленного подключения TLS.
ssl_enabled Значение "Включено", если подключение работает в режиме TLS. В противном случае — пустая строка.
uri_path Определяет конкретный ресурс на узле, к которому требуется доступ из веб-клиента. Это часть URI запроса без аргументов. Пример: в запросе http://contoso.com:8080/article.aspx?id=123&title=fabrikam uri_path будет иметь значение /article.aspx

Переменные сервера взаимной проверки подлинности

Шлюз приложений поддерживает следующие переменные сервера для взаимной проверки подлинности. Используйте эти серверные переменные так же, как и при работе с другими переменными сервера.

Имя переменной Description
client_certificate Сертификат клиента для установленного SSL-соединения в формате PEM.
client_certificate_end_date Дата окончания действия сертификата клиента.
client_certificate_fingerprint Отпечаток SHA1 сертификата клиента для установленного SSL-соединения.
client_certificate_issuer Значение строки "issuer DN" сертификата клиента для установленного SSL-соединения.
client_certificate_serial Серийный номер сертификата клиента для установленного SSL-соединения.
client_certificate_start_date Дата начала действия сертификата клиента.
client_certificate_subject Значение строки "subject DN" сертификата клиента для установленного SSL-соединения.
client_certificate_verification Результат проверки сертификата клиента: SUCCESS, FAILED:<reason> или NONE, если сертификат отсутствует.

Конфигурация перезаписи

Чтобы настроить правило перезаписи, необходимо создать набор правил перезаписи и добавить в него конфигурацию правила перезаписи.

Набор правил перезаписи содержит:

  • Сопоставление правил маршрутизации запросов: конфигурация перезаписи связана с прослушивателем источника с помощью правила маршрутизации. При использовании базового правила маршрутизации конфигурация перезаписи связывается с прослушивателем источника, и выполняется перезапись глобального заголовка. При использовании правила маршрутизации на основе пути конфигурация перезаписи заголовка определяется в сопоставлении URL-пути. Поэтому в данном случае она применяется только к области конкретного пути на сайте. Можно создать несколько наборов правил перезаписи и применить каждый набор перезаписи к нескольким прослушивателям. Однако вы можете применить только один набор правил перезаписи к конкретному прослушивателю.

  • Rewrite Condition (Условие переопределения). Является необязательным параметром. Условия перезаписи оценивают содержимое запросов и ответов HTTP(S). Действие перезаписи будет выполнено, если запрос или ответ HTTP(S) соответствует условию перезаписи. При связывании более одного условия с действием оно выполняется только при соблюдении всех условий. Иными словами, операция является логической операцией "И" (AND).

  • Rewrite type (Тип переопределения). Доступны три типа переопределения:

    • Перезапись заголовков запросов
    • Перезапись заголовков ответов
    • Перезапись компонентов URL-адреса
      • URL path (URL-путь). Значение, которое следует использовать для переопределения пути.
      • URL Query String (Строка запроса URL-адреса). Значение, которое следует использовать для переопределения строки запроса.
      • Повторное вычисление карты пути: используется для определения того, должна ли карта ПУТИ URL-адреса быть переоценены или нет. Если флажок не установлен, исходный URL-адрес будет использоваться для сопоставления шаблона пути на карте URL-пути. Если задано значение true, карта пути URL-адреса будет переоценена, чтобы проверка совпадение с перезаписным путем. Включение этого параметра помогает в маршрутизации запроса к другому внутреннему пулу после перезаписи.

Распространенные ошибки конфигурации перезаписи

  • Включение сопоставления путей повторной оценки запрещено для основных правил маршрутизации запросов. Это позволяет предотвратить бесконечный цикл оценки для базового правила маршрутизации.

  • Необходимо иметь по крайней мере 1 правило условной перезаписи или 1 правило перезаписи, которое не включает функцию "Повторно оценить карту пути" для правил маршрутизации на основе пути, чтобы предотвратить бесконечный цикл оценки для правила маршрутизации на основе пути.

  • Входящие запросы будут завершаться кодом ошибки 500, если цикл создается динамически на основе входных данных клиента. При таком сценарии Шлюз приложений продолжит обслуживать другие запросы без ухудшения.

Использование переопределения URL-адреса или перезаписи заголовка узла с брандмауэром веб-приложения (WAF_v2 SKU)

При настройке переопределения URL-адресов или перезаписи заголовка узла, оценка WAF будет происходить после процедуры перезаписи заголовка запроса или параметров URL-адреса. При удалении конфигурации перезаписи URL-адреса или перезаписи заголовка узла в шлюзе приложений, оценка WAF будет выполнена до процедуры перезаписи. Этот порядок гарантирует, что правила WAF применяются к окончательному запросу, который будет получен внутренним пулом.

Например, предположим, что у вас есть следующее правило перезаписи заголовка для заголовка "Accept" : "text/html". Если значение заголовка "Accept" равно "text/html", значение будет переписано на "image/png".

В этом случае, если настроена только перезапись заголовков, оценка WAF будет выполняться в момент "Accept" : "text/html". Но при настройке переопределения URL-адресов или перезаписи заголовка узла оценка WAF будет выполняться на момент "Accept" : "image/png".

Распространенные сценарии для перезаписи заголовков

Удаление информации о портах из заголовков X-Forwarded-For

Шлюз приложений вставляет заголовок X-Forwarded-For во все запросы перед их перенаправлением в серверную часть. Этот заголовок представляет собой разделенный запятыми список IP-портов. Могут возникнуть сценарии, в которых серверные серверы должны содержать только заголовки, чтобы содержать IP-адреса. Можно использовать перезапись заголовка для удаления сведений о портах из заголовка X-Forwarded-For. Один из способов сделать это — задать в качестве заголовка переменную сервера add_x_forwarded_for_proxy. Также можно использовать переменную client_ip:

Remove port

Изменение URL-адреса перенаправления

Изменение URL-адреса перенаправления может оказаться полезным при определенных обстоятельствах. Например, клиенты были первоначально перенаправлены на путь, например "/blog", но теперь должны отправляться в "/updates" из-за изменения структуры содержимого.

Предупреждение

Иногда требуется изменить URL-адрес перенаправления в контексте конфигурации, в которой Шлюз приложений настроено переопределение имени узла на серверную часть. Имя узла, как показано серверной частью, отличается от имени узла, как показано в браузере. В этой ситуации перенаправление не будет использовать правильное имя узла. Такую конфигурацию использовать не рекомендуется.

Ограничения и последствия такой конфигурации описаны в разделе "Сохранить исходное имя узла HTTP" между обратным прокси-сервером и серверным веб-приложением. Рекомендуемая настройка для Служба приложений — следовать инструкциям в разделе "Пользовательский домен (рекомендуется)" в разделе "Настройка Служба приложений с помощью Шлюз приложений". Перезапись заголовка расположения в ответе, как описано в приведенном ниже примере, следует считать обходным решением и не устранять первопричину.

При отправке ответа перенаправления служба приложений использует то же имя узла в заголовке расположения своего ответа, что и в запросе, полученном от шлюза приложений. Поэтому клиент будет отправлять запрос напрямую в contoso.azurewebsites.net/path2, а не через шлюз приложений (contoso.com/path2). Обход шлюза приложений нежелателен.

Эту проблему можно устранить, установив параметр имени узла в заголовке расположения в значение доменного имени шлюза приложений.

Ниже приведены действия по замене имени узла.

  1. Создайте правило перезаписи с условием, которое оценивает наличие в заголовке расположения фрагмента "azurewebsites.net". Введите шаблон (https?):\/\/.*azurewebsites\.net(.*)$.
  2. Выполните перезапись заголовка расположения так, чтобы в нем было указано имя узла шлюза приложений. Для этого введите в {http_resp_Location_1}://contoso.com{http_resp_Location_2} качестве значения заголовка. Кроме того, можно также использовать переменную сервера host, чтобы задать имя узла в соответствии с исходным запросом.

Modify location header

Реализация безопасности заголовков HTTP для предотвращения возникновения уязвимостей

Вы можете устранить ряд уязвимостей системы безопасности, реализовав необходимые заголовки в ответе приложения. К этим заголовкам относятся X-XSS-Protection, Strict-Transport-Security и Content-Security-Policy. Задать эти заголовки для всех ответов можно с помощью шлюза приложений.

Security header

Удаление ненужных заголовков

Вам может понадобиться удалить заголовки, которые раскрывают конфиденциальную информацию из HTTP-ответа. Например, может потребоваться удалить такие сведения, как имя внутреннего сервера, операционная система или сведения о библиотеке. Для удаления этих заголовков можно использовать шлюз приложений:

Deleting header

Проверка наличия заголовка

Вы можете оценить HTTP-запрос или заголовок ответа на наличие заголовка или переменной сервера. Эта оценка будет полезна, если требуется выполнить перезапись заголовка только при наличии определенного заголовка.

Checking presence of a header

Распространенные сценарии для переопределения URL-адресов

Выбор пути на основе параметров

Если необходимо выбрать серверный пул на основе значения заголовка, части URL-адреса или строки запроса в самом запросе, можно использовать сочетание возможностей переопределения URL-адресов и маршрутизации на основе пути. Например, если у вас есть веб-сайт для осуществления покупок, а категория продуктов передается в качестве строки запроса в URL-адресе и вы хотите направить запрос на серверную часть на основе строки запроса, то:

Шаг 1. Создайте карту пути, как показано на рисунке ниже

URL rewrite scenario 1-1.

Шаг 2 (А). Создайте набор перезаписи, который содержит 3 правила перезаписи.

  • Первое правило имеет условие, проверяющее переменную query_string для category=shoes и имеет действие, которое перезаписывает путь URL-адреса в /listing1 со включенным повторным вычислением карты пути.

  • Второе правило имеет условие, проверяющее переменную query_string для category=bags и имеет действие, которое перезаписывает путь URL-адреса в /listing2 со включенным повторным вычислением карты пути.

  • Третье правило имеет условие, проверяющее переменную query_string для category=accessories и имеет действие, которое перезаписывает путь URL-адреса в /listing3 со включенным повторным вычислением карты пути.

URL rewrite scenario 1-2.

Шаг 2 (Б). Свяжите этот набор перезаписи с путем по умолчанию для приведенного выше правила на основе пути

URL rewrite scenario 1-3.

Теперь, если пользователь запрашивает contoso.com/listing?Category=any, он будет сопоставлен с путем по умолчанию, так как ни один из шаблонов путей в карте пути (/listing1,/listing2,/listing3) не будет совпадать. Так как вы связали приведенный выше набор перезаписи с этим путем, далее будет произведена оценка набора перезаписи. Так как строка запроса не будет соответствовать условию в любом из 3 правил перезаписи в этом наборе перезаписи, действие перезаписи не будет выполнено, поэтому запрос будет перенаправлен в серверную часть, связанную с путем по умолчанию (который является GenericList).

Если пользователь запрашивает contoso.com/listing?category=shoes, то снова будет найден путь по умолчанию. Однако в этом случае условие в первом правиле будет соответствовать, поэтому действие, связанное с условием, будет выполнено, которое перезаписывает путь URL-адреса в /листинг1 и переоценит схему пути. При повторном вычислении карты пути запрос будет соответствовать пути, связанному с шаблоном /list1 , и запрос будет перенаправлен на серверную часть, связанную с этим шаблоном, которая является ShoesListBackendPool.

Примечание.

Этот сценарий может быть расширен до любого значения заголовка или файла cookie, пути URL-адреса, строки запроса или серверных переменных на основе определенного условия и, по сути, позволяет маршрутизировать запросы на основе этих условий.

Перепись параметры строки запроса на основе URL-адреса

Рассмотрим сценарий веб-сайта для покупок, где видимая пользователю ссылка должна быть простой и удобочитаемой, но на внутреннем сервере требуются параметры строки запроса для отображения правильного содержимого.

В этом случае шлюз приложений может записывать параметры из URL-адреса и добавлять пары "ключ-значение" для строки запроса из URL-адреса. Предположим, что пользователю требуется переписать https://www.contoso.com/fashion/shirts на https://www.contoso.com/buy.aspx?category=fashion&product=shirts. Это можно сделать с помощью следующей конфигурации переопределения URL-адреса.

Условие — если переменная сервера uri_path равна шаблону /(.+)/(.+)

URL rewrite scenario 2-1.

Действие — задать URL-путь в значение buy.aspx, а строку запроса — в значение category={var_uri_path_1}&product={var_uri_path_2}

URL rewrite scenario 2-2.

Пошаговые инструкции по выполнению описанного выше сценария см. в статье Перезапись URL-адреса с помощью шлюза приложений на портале Azure

Сравнение переопределения URL-адреса и перенаправления URL-адреса

Для перезаписи URL-адреса Шлюз приложений перезаписывает URL-адрес перед отправкой запроса в серверную часть. Это не изменит то, что пользователи видят в браузере, так как изменения скрыты от пользователя.

Для перенаправления URL-адресов Шлюз приложений отправляет клиенту ответ перенаправления с новым URL-адресом. Это, в свою очередь, требует, чтобы клиент повторно отправлял свой запрос на новый URL-адрес, указанный в перенаправлении. URL-адрес, который пользователь видит в браузере, будет обновлен до нового URL-адреса.

Rewrite vs Redirect.

Ограничения

  • Если в ответе содержится несколько заголовков с одним и тем же именем, то перезапись значения одного из этих заголовков приведет к удалению других заголовков в ответе. Обычно это происходит с заголовком Set-Cookie, так как в ответе может быть несколько заголовков Set-Cookie. Один из таких сценариев заключается в использовании службы приложений с шлюзом приложений и настройке сопоставления сеансов на основе файлов cookie в шлюзе приложений. В этом случае ответ будет содержать два заголовка Set-Cookie: один используется службой приложений, например Set-Cookie: ARRAffinity=ba127f1caf6ac822b2347cc18bba0364d699ca1ad44d20e0ec01ea80cda2a735;Path=/;HttpOnly;Domain=sitename.azurewebsites.net, а другой — для сходства шлюза приложений, например Set-Cookie: ApplicationGatewayAffinity=c1a2bd51lfd396387f96bl9cc3d2c516; Path=/. Перезапись одного из заголовков Set-Cookie в этом сценарии может привести к удалению другого заголовка Set-Cookie из ответа.
  • Перезаписи не поддерживаются, если шлюз приложений настроен для перенаправления запросов или отображения пользовательской страницы ошибок.
  • Имена заголовков запросов могут содержать буквенно-цифровые символы и дефисы. Имена заголовков, содержащих другие символы, будут не карта при отправке запроса на серверный целевой объект.
  • Имена заголовков ответа могут содержать любые буквенно-цифровые символы и определенные символы, как определено в RFC 7230.
  • Заголовки подключения и обновления не подлежат перезаписи
  • Перезаписи не поддерживаются для ответов 4xx и 5xx, созданных непосредственно из Шлюз приложений

Следующие шаги