Заметки: Передача имени из SNI на upstream в Nginx

Передача имени из SNI на upstream-серверы может потребоваться в том случае, если бэкэнд-приложение жестко завязано на имени сервиса. В этом случае необходимо изменить ряд настроек по умолчанию на Nginx


Если вам интересна тематика Debian и связанных с ним приложений, рекомендую обратиться к тегу Debian на моем блоге.


Передача имени ресурса из SNI

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


Предлагаю ознакомиться с другими статьями про Nginx на моем блоге:

Приятного чтения!


Теория

Несмотря на то, что Nginx распределяет запросы пользователей по бэкэнд-серверам исходя из имени ресурса в SNI, на бэкэнды он этот параметр по умолчанию не передает. То есть, бэкэнд вероятнее всего увидит обращение по его собственному ip-адресу, а не красивый fqdn. Все бы ничего, но для некоторых сервисов (например Windows Server WAP) такое поведение может быть нежелательным и они будут обрывать соединение (RST, ACK) сразу после TLS Client Hello от Nginx. Вот как это выглядит в WireShark:

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

Если включить дебаг в Nginx, то можете получать подобные сообщения:

Примечание: пример выше — строка из лога общения обратного прокси на Nginx с Windows Server WAP, через который опубликован сервис AD FS.

В нем содержится как причина разрыва соединения — peer closed connection in SSL handshake (104: Connection reset by peer) while SSL handshaking to upstream — так и конечный URL, который дошел до бэкэнд-сервера — https://10.16.1.51:443/adfs/ls/idpinitiatedsignon.htm. Итого, наша задача — передавать на upstream-серверы имя ресурса, по которому изначально обращается клиент.

Настройки

Первой и самой главной опцией, разрешающей передачу имени ресурса на upstream-серверы, является proxy_ssl_server_name 1. Необходимо выставить её в значение on и определить имя ресурса в директиве proxy_pass. Выглядеть это будет следующим образом (это первый вариант):

Второй вариант заключается в переопределении имени ресурса в нужной вам секции конфигурации Nginx. Для этого нужны параметры:

  • proxy_ssl_name 2 — переопределяет имя сервера;
  • proxy_set_header 3 — переопределяет необходимые поля заголовка запроса. В нашем случае понадобится заголовок Host.

В моем случае устанавливать нужное имя ресурса логично в секции location {}. Итак, получаем:

Как итог — сервис работает нормально.

comments powered by HyperComments
Яндекс.Метрика