Техническое: опция, отклоняющая TLS-соединение в Nginx
В свежих версиях веб-сервера Nginx есть полезная (и довольно экзотическая) опция для настройки TLS: ssl_reject_handshake (on | off), о которой, оказывается, мало кто знает. Опция позволяет управлять прерыванием процесса установления TLS-соединения (“хендшейка”) на стороне сервера. С помощью “ssl_reject_handshake on;” можно отклонить TLS-соединение, если в клиентском ClientHello указано имя хоста (поле SNI), которого нет на стороне сервера.
Почему это удобно. Штатная работа веб-сервера по HTTPS подразумевает, что при установлении TLS-соединения клиент передаёт имя хоста, соответствующее DNS-имени веб-узла; например, для https://test.ru/ это будет test.ru. Однако никто не запрещает клиенту обратиться с другим именем хоста в SNI. Более того, на тот же самый IP-адрес, который соответствует веб-узлу под именем test.ru, может быть направлено другое DNS-имя (другой домен). Веб-браузеры, обращающиеся по такому имени, будут указывать его в SNI, а сервер, при прочих равных, не сможет найти не только соответствующий “виртуальный хост” в конфигурации, но и подобрать корректный TLS-сертификат. Однако какой-то TLS-сертификат для установления TLS-соединения серверу нужен и, без дополнительных мер, это приводит к тому, что сервер отвечает с “первым попавшимся” (буквально) серверным TLS-сертификатом из сконфигурированных.
Если на сервере всего один виртуальный хост/веб-узел (или настроены отдельные IP-адреса для отдельных веб-узлов), то ничего нового клиент не узнаёт. Однако если виртуальных хостов много, то ответ с произвольным сертификатом приводит к нежелательным утечкам имён: клиент получит сертификат, в котором будет указано имя другого сервиса, доступного на этом же узле (или несколько имён). Администраторы и даже DevOps об этом постоянно забывают.
Сделать тут что-то корректное на уровне HTTP невозможно в принципе, так как TLS-соединение устанавливается раньше, а для каждого HTTP-ответа (403 и пр.) потребуется подходящий по имени доверенный сертификат. Да, возможны различные “костыли”, вроде использования заведомо несовпадающего сертификата-заглушки, но все они подразумевают некорректный ответ.
Указание “ssl_reject_handshake on;” для default_server (для имени хоста по умолчанию) позволяет побороть только что описанную проблему: Nginx будет прерывать именно TLS-соединение, если клиент обращается с неверным именем хоста в SNI – это, что называется, технически строгий способ. Браузер, в таком случае, выведет сообщение о недоступности узла, а не предупреждение о несовпадении имён, которое пользователи привыкли преодолевать при помощи кнопки “Всё равно продолжить”.
Адрес записки: https://dxdt.ru/2024/03/27/12631/
Похожие записки:
- Encrypted Client Hello и браузеры Google
- Ретроспектива заметок: программный код из "реальности" в "виртуальности"
- Реплика: уточнение о языках программирования
- Реплика: пример про ДСЧ
- Продолжение сегментации: Docker Hub
- Экспериментальный сервер TLS: сигналы внутри сертификата
- Детектирование текстов, сгенерированных ИИ
- Gofetch как уязвимость
- Совпадения тегов ключей DNSSEC и парадокс дней рождения
- Описание TLS в поисковых машинах
- Сайт OpenSSL и сегментация интернетов
Написать комментарий