TLS Server Name Indication (SNI) на практике: совместимость, безопасность и диагностика
Практическое руководство по SNI: совместимость, риски приватности, диагностика через OpenSSL/curl, настройка на Nginx/Apache/HAProxy и чек-лист.
TLS Server Name Indication (SNI) на практике: совместимость, безопасность и диагностика
Зачем нужен SNI
SNI (RFC 6066) позволяет одному IP-адресу обслуживать множество HTTPS-хостов с разными сертификатами. Это основа современного shared-хостинга, SaaS и multi-tenant инфраструктур. Ошибки в SNI приводят к предупреждениям безопасности, недоступности сервисов и проблемам с аудитом.
Как работает TLS Handshake с SNI
- ClientHello содержит extension ‘server_name’ с целевым hostname.
- Сервер выбирает сертификат и цепочку под этот hostname.
- Если SNI не совпадает с сертификату — разрыв или предупреждение (в зависимости от клиента/сервера).
- При отсутствии SNI (старые клиенты) сервер отдаёт default certificate.
Совместимость
-
Поддержка: практически все современные клиенты (браузеры, curl, wget, языки) поддерживают SNI.
| Клиент/Язык | SNI по умолчанию | Особенности |
|---|---|---|
| Браузеры | Да | |
| curl | Да; можно отключить --tls-sni | Полезно для диагностики |
| OpenSSL s_client | Требует -servername | |
| Java (JSSE) | Да; важен правильный HostnameVerifier | |
| Go | Да; настраивается через ServerName в tls.Config | |
| Python (requests/urllib3) | Да | | -
Проблемы: старые устройства/ОС (Windows XP, старые embedded), нестандартные клиенты без SNI.
Безопасность и приватность
- SNI раскрывает запрашиваемый hostname в открытом виде в ClientHello. Это метаданные.
- ECH (Encrypted Client Hello, RFC 9460) решает проблему, но требует поддержки на клиенте и сервере (DoH/DoT, совместимые прокси/CDN).
- Риски: утечка структуры доменов, профилирование трафика.
- Меры: ECH при возможности; иначе — минимизация числа wildcard и чёткое разделение tenant по endpoint’ам.
Диагностика
OpenSSL
# С SNI
openssl s_client -connect host:443 -servername example.com -tlsextdebug < /dev/null
# Без SNI
openssl s_client -connect host:443 -noservername < /dev/null
curl
# Явно задать SNI/Host
curl -vI https://example.com --resolve example.com:443:1.2.3.4 --header "Host: example.com"
# Отключить SNI для теста
curl -vI https://1.2.3.4 --connect-to ::1.2.3.4 --header "Host: example.com" --tls-sni 0
nmap
nmap --script ssl-cert,ssl-enum-ciphers -p 443 host
Серверные платформы
- Nginx:
server_nameи отдельныеserver {}блоки; default_server для fallback. - Apache:
NameVirtualHostиVirtualHostс ServerName/ServerAlias. - HAProxy:
sni req.ssl_sniв frontend/backend, ACL по SNI. - CDN/WAF: корректно проксируйте SNI; следите за сохранением Host и consistency сертификатов.
Чек-лист внедрения
- Для каждого tenant/hostname — свой сертификат или корректный SAN/UCC.
- Настроен default сертификат для клиентов без SNI.
- Проверены legacy-пути (если поддерживаются) и их изоляция.
- Включён мониторинг ошибок TLS (handshake_failure, unknown_name).
- Проверена консистентность сертификатов на всех endpoint’ах (HA/CDN).
- Оценена применимость ECH; при невозможности — документирован риск раскрытия SNI.
Теги
TLS, SNI, SSL, безопасность, диагностика, совместимость, ECH, HTTPS, Nginx, HAProxy
Категории
Безопасность, Системное администрирование