SNI (Server Name Indication) — это расширение протокола TLS, позволяющее клиенту указать имя хоста, к которому он пытается подключиться, на начальном этапе рукопожатия TLS, что критично для прокси-серверов при маршрутизации и обработке зашифрованного трафика к множеству доменов на одном IP-адресе.
SNI: Основы работы
Проблема виртуальных хостов и появление SNI
До появления SNI, когда клиент устанавливал TLS-соединение с сервером, сервер должен был представить свой сертификат. Если на одном IP-адресе и порту располагалось несколько доменов (виртуальных хостов), каждый со своим уникальным TLS-сертификатом, сервер не мог определить, какой именно сертификат отправить клиенту до того, как клиент отправит HTTP-запрос (который находится внутри зашифрованного TLS-трафика). Это приводило к проблемам, так как TLS-рукопожатие происходит до обмена HTTP-данными. Сервер мог либо использовать один универсальный сертификат (что не всегда возможно или безопасно), либо требовать отдельный IP-адрес для каждого защищенного домена.
SNI было разработано для решения этой проблемы. Оно позволяет клиенту добавить имя домена (hostname) в сообщение Client Hello на первом этапе TLS-рукопожатия. Таким образом, сервер может использовать это имя для выбора соответствующего TLS-сертификата из нескольких, ассоциированных с одним IP-адресом.
Механизм SNI в TLS-рукопожатии
TLS-рукопожатие начинается с сообщения Client Hello от клиента. В этом сообщении клиент предлагает список поддерживаемых версий TLS, наборов шифров и расширений. SNI является одним из таких расширений.
Структура расширения SNI в Client Hello включает:
- Type: Указывает, что это расширение SNI (обычно 0x0000).
- Length: Длина поля данных расширения.
- Server Name List: Список имен серверов. На практике обычно содержит одно имя.
- Name Type: Тип имени (например, hostname — 0x00).
- Name Length: Длина имени хоста.
- Server Name: Само имя хоста (например, www.example.com).
Пример фрагмента Client Hello с SNI:
TLSv1.2 Record Layer: Handshake Protocol: Client Hello
Handshake Protocol: Client Hello
Version: TLS 1.2 (0x0303)
Random: ...
Session ID Length: 0
Cipher Suites Length: ...
Cipher Suites: ...
Compression Methods Length: ...
Compression Methods: ...
Extensions Length: ...
Extensions:
...
Extension: server_name (len=22)
Type: server_name (0)
Length: 20
Server Name Indication extension
Server Name list length: 18
Server Name Type: Host Name (0)
Server Name length: 15
Server Name: www.example.com
...
Получив Client Hello с расширением SNI, сервер идентифицирует запрошенный домен и отвечает сообщением Server Hello, включая соответствующий сертификат для этого домена.
Обработка SNI различными типами прокси
Прокси-серверы играют ключевую роль в сетевой инфраструктуре, и их взаимодействие с SNI зависит от типа прокси и его функциональности.
Прямые (Forward) прокси и метод CONNECT
Прямой прокси действует как посредник между клиентом и внешним сервером. Для HTTP-трафика прокси просто пересылает запросы. Однако для HTTPS-трафика, который по своей природе зашифрован, прокси не может просто прочитать HTTP-запрос. Вместо этого клиенты используют метод CONNECT.
-
Клиент отправляет
CONNECTзапрос прокси:
http CONNECT www.example.com:443 HTTP/1.1 Host: www.example.com:443 Proxy-Connection: Keep-Alive
В этом запросе прокси-серверу сообщается только домен и порт, к которому клиент хочет подключиться. -
Прокси устанавливает TCP-соединение:
Прокси устанавливает TCP-соединение сwww.example.comна порту443. -
Прокси отвечает клиенту:
http HTTP/1.1 200 Connection established -
TLS-рукопожатие:
После установления соединения клиент начинает TLS-рукопожатие через прокси. В сообщенииClient Helloклиент включает расширение SNI, указывающееwww.example.com. Прокси, не расшифровывая трафик, просто пересылает этотClient Helloна целевой сервер.
Роль SNI для прямого прокси:
- Маршрутизация: Хотя CONNECT уже указывает целевой домен, SNI подтверждает его. В некоторых случаях прокси может использовать SNI для дополнительной валидации или специфической маршрутизации.
- Фильтрация и логирование (без интерцепции): Без расшифровки трафика, прямой прокси может использовать информацию из CONNECT запроса и, в некоторых продвинутых конфигурациях, из SNI (если прокси способен анализировать Client Hello без расшифровки всего потока) для базовой фильтрации или логирования целевых доменов.
Обратные (Reverse) прокси
Обратный прокси находится перед одним или несколькими веб-серверами (бэкендами) и перенаправляет клиентские запросы к ним. Клиент думает, что общается непосредственно с целевым сервером.
Для HTTPS-трафика обратный прокси обычно сам завершает TLS-соединение с клиентом. Это означает, что он принимает Client Hello, расшифровывает его и анализирует SNI.
Роль SNI для обратного прокси:
- Выбор сертификата: Обратный прокси использует SNI из Client Hello, чтобы выбрать правильный TLS-сертификат для отправки клиенту, если он обслуживает несколько доменов на одном IP-адресе.
- Маршрутизация к бэкендам: После успешного TLS-рукопожатия и расшифровки трафика, обратный прокси может использовать информацию из HTTP-запроса (например, заголовок Host) для маршрутизации к соответствующему бэкенд-серверу. Однако SNI позволяет принять решение о маршрутизации еще до расшифровки HTTP-запроса, что может быть использовано для более раннего принятия решений или для маршрутизации, основанной исключительно на имени хоста, если бэкенды различаются только по доменному имени.
- Балансировка нагрузки: SNI может использоваться как критерий для распределения трафика между различными группами бэкенд-серверов.
Пример конфигурации Nginx (как обратного прокси) для обработки SNI:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
location / {
proxy_pass http://backend_example_com;
proxy_set_header Host $host;
}
}
server {
listen 443 ssl;
server_name www.anothersite.com;
ssl_certificate /etc/nginx/ssl/anothersite.com.crt;
ssl_certificate_key /etc/nginx/ssl/anothersite.com.key;
location / {
proxy_pass http://backend_anothersite_com;
proxy_set_header Host $host;
}
}
В этом примере Nginx использует server_name для сопоставления с SNI, представленным клиентом, и выбирает соответствующий блок server для обработки соединения и выбора сертификата.
Прозрачные (Transparent) прокси
Прозрачный прокси перехватывает сетевой трафик без явной настройки со стороны клиента. Для HTTP-трафика он работает как обычный прокси. Для HTTPS-трафика он обычно выполняет TLS-интерцепцию (MITM).
Роль SNI для прозрачного прокси:
- Идентификация цели для интерцепции: Прозрачный прокси перехватывает Client Hello и извлекает SNI, чтобы определить, какой домен запрашивается. Это критически важно для генерации поддельного сертификата для этого домена.
- Принятие решения об интерцепции: На основе SNI прокси может решить, следует ли интерцептировать соединение, или же просто пропустить его без расшифровки (например, для банковских сайтов).
- Маршрутизация: После определения целевого домена через SNI, прокси устанавливает собственное соединение с реальным сервером, используя то же SNI.
SNI и функции безопасности/маршрутизации прокси
Маршрутизация и балансировка нагрузки
Прокси используют SNI для интеллектуальной маршрутизации трафика:
- Географическая маршрутизация: Направление клиентов к ближайшим серверам или к серверам в определенном регионе на основе SNI.
- Мультитенантность: Разделение трафика для разных клиентов или приложений, использующих один и тот же прокси-инфраструктуру, на основе их доменных имен в SNI.
- Балансировка нагрузки: Хотя основной механизм балансировки нагрузки для HTTPS обычно опирается на HTTP-заголовки после расшифровки, SNI может использоваться для предварительной балансировки на основе домена, прежде чем будет установлен полный TLS-сеанс с бэкендом.
Фильтрация и контроль доступа
SNI позволяет прокси-серверам применять политики безопасности и контроля доступа к зашифрованному трафику на ранней стадии:
- Блокировка доменов: Прокси может заблокировать доступ к определенным доменам, анализируя SNI в Client Hello, до того как будет установлено полное TLS-соединение.
- Категоризация трафика: SNI может использоваться для категоризации трафика (например, социальные сети, новости, финансовые сервисы) и применения различных политик (например, ограничение пропускной способности, временной доступ).
- Обход интерцепции: Для чувствительных доменов (например, онлайн-банкинг), прокси может быть настроен на пропуск TLS-соединения без интерцепции, основываясь на SNI.
TLS-интерцепция (MITM)
TLS-интерцепция (Man-in-the-Middle) — это процесс, при котором прокси расшифровывает HTTPS-трафик, анализирует его, а затем повторно шифрует для отправки на целевой сервер. SNI является необходимым компонентом для этой операции:
1. Клиент отправляет Client Hello с SNI.
2. Прокси перехватывает Client Hello и извлекает SNI.
3. Прокси генерирует поддельный TLS-сертификат для домена, указанного в SNI, подписанный собственным корневым сертификатом прокси (который должен быть доверенным на клиенте).
4. Прокси отправляет Server Hello с поддельным сертификатом клиенту.
5. Клиент устанавливает TLS-соединение с прокси.
6. Прокси устанавливает отдельное TLS-соединение с реальным целевым сервером, используя SNI из оригинального Client Hello.
7. Прокси расшифровывает трафик от клиента, анализирует его, применяет политики, а затем повторно шифрует и отправляет на целевой сервер.
Без SNI прокси не смог бы определить, какой сертификат генерировать и к какому домену подключаться на стороне сервера.
Вызовы и будущее SNI для прокси
Шифрование SNI (ESNI/ECH)
SNI, хотя и решает проблему виртуальных хостов, имеет недостаток с точки зрения приватности: имя целевого домена передается в открытом виде в Client Hello. Это позволяет любому промежуточному узлу (провайдеру, прокси, государственным органам) узнать, к какому сайту подключается пользователь, даже если остальной трафик зашифрован.
Для решения этой проблемы было разработано расширение Encrypted SNI (ESNI), а затем его преемник Encrypted Client Hello (ECH). ECH шифрует всё сообщение Client Hello, включая SNI.
Влияние ESNI/ECH на прокси:
- Потеря видимости: Прокси-серверы, которые полагаются на открытый SNI для маршрутизации, фильтрации или TLS-интерцепции, теряют эту возможность при использовании ECH.
- Сложности с фильтрацией и безопасностью: Без доступа к имени домена в Client Hello, прокси становится сложнее применять политики безопасности (например, блокировку вредоносных сайтов) на раннем этапе TLS-рукопожатия.
- Изменение архитектуры прокси: Для сохранения функциональности прокси могут потребоваться новые подходы, например, использование DNS-записей для определения целевого домена (если клиент запрашивает DNS через прокси) или более глубокий анализ трафика после установления соединения (что сложнее и ресурсозатратнее).
- Для обратных прокси: В сценарии с обратным прокси, если прокси сам владеет ключом для расшифровки ECH, он может продолжать функционировать, поскольку он является конечной точкой TLS для клиента. Однако для прямых и прозрачных прокси это становится значительным вызовом.
Влияние на приватность и безопасность
Внедрение ECH улучшает приватность пользователей, скрывая их сетевую активность от посторонних. Однако это также создает вызовы для сетевых администраторов и провайдеров безопасности, которые используют SNI для обеспечения безопасности и контроля. Баланс между приватностью пользователя и возможностями сетевого контроля остается предметом активных дискуссий и развития технологий.