SNI расшифровывается как Server Name Indication, и это небольшое расширение протокола TLS определило экономику современного хостинга сильнее, чем многие более заметные технологии. До его появления один IP-адрес мог удерживать только один HTTPS-сертификат, и инженер, поднимая второй защищённый сайт, обязан был купить или выпросить ещё один адрес. Расширение server_name, которое клиент присылает в самом первом сообщении рукопожатия, сломало это правило и открыло эпоху, когда сотня сайтов живёт за одним адресом, а отдельный IP стал роскошью, а не нормой. Платили за это удобство приватностью: имя, которое клиент называет так охотно, десятилетиями летело по сети открытым текстом, его читали системы фильтрации провайдера и любые наблюдатели на маршруте. История SNI это история о том, как практичный инженерный костыль стал опорой индустрии, а его побочный эффект долго пытались закрыть новым слоем шифрования.
Как устроено рукопожатие и почему сервер не знал чей показать сертификат
Чтобы понять первоначальную проблему, нужно вспомнить порядок исторический. Он возник из очерёдности протоколов, а не из чьей-то глупости. Когда браузер стучится на порт 443, первым делом начинается TLS-рукопожатие: клиент шлёт ClientHello, сервер отвечает ServerHello и предъявляет свой сертификат. Только после того как канал защищён, внутри него полетит HTTP-запрос с заголовком Host, где браузер наконец сообщает, какого сайта он хочет. Обратите внимание на очерёдность событий: сертификат нужен до того, как станет известно имя хоста.
Для HTTP это не было проблемой. На обычном восьмидесятом порту сначала выполнялся запрос, Host приходил сразу, и веб-сервер спокойно выбирал между сотнями виртуальных хостов. С криптографией всё перевернулось: сервер обязан доказать кто он, прежде чем узнает кого перед ним просят. Если за одним адресом живёт один сайт, вопроса нет, сертификат один и выбор тривиален. Если за тем же адресом поселили два сайта, сервер оказывается продавцом на базаре, который закрыл глаза и достаёт товар наугад: угадал сертификат, соединение живёт, не угадал, браузер краснеет и предупреждает о несоответствии имени.
Поэтому долгое действовало простое правило: один IP, один сертификат. Хостеры назначали каждому защищённому сайту выделенный адрес, брали за это деньги, а региональные регистратуры мрачно смотрели на таяние пула IPv4. Были обходные пути вроде одного сертификата с длинным списком альтернативных имён, но он требовал перевыпуска при каждом новом клиенте и раскрывал посторонним весь список арендаторов. Wildcard помогал внутри одного домена и никак между чужими доменами. Проблема зрела и пахла, и обществу потребовался механизм, который перенесёт выбор сертификата на более ранний этап.
Расширение server_name в ClientHello и сто сайтов на одном адресе
Решение оказалось на удивление скромным. В стандарте TLS, в документе RFC 3546, а позже с уточнениями в RFC 6066, описали расширение server_name. Механика предельно проста: клиент, открывая рукопожатие, прямо в ClientHello пишет имя хоста, к которому идёт. Сервер читает эту строку, заглядывает в свою таблицу виртуальных хостов, достаёт подходящий сертификат и предъявляет именно его. Всё, проблема решена, причём без единого нового криптографического примитива - просто клиент сообщил дополнительную подсказку.
Эффект на индустрию оказался колоссальным и почти мгновенным. Виртуальный хостинг с HTTPS таким же дешёвым, каким был обычный: сотня сайтов на одном адресе, сертификат каждого выбирается по имени во время рукопожатия, клиенту хостинга не нужен выделенный IP. Провайдеры вздохнули с облегчением, потому что дефицит адресов перестал расти скачками с каждым новым защищённым магазином. Браузеры приняли расширение быстро, задержка образовалась лишь из-за легаси-парк: старые библиотеки и экзотические клиенты не шли звать Имени, и ради приходилось держать дефолтный сертификат и стратегию для несносимых гостей.
Появилась и целая дисциплина выбора поведения. Администратор решает, что происходит, когда server_name отсутствует вовсе: обычно сервер показывает сертификат по умолчанию либо призрачно рвёт соединение. Решает и что отвечать на неизвестное имя. В крупных сетях эти политики документируются так же тщательно, как маршрутизация, потому что от них зависит, увидит ли обходящий реестры бот рабочий сайт или стену отказа. Скромное расширение меняет не только криптографию канала, но и топологию обслуживания: балансировщики на входе ферм теперь читают ClientHello, суёт свои лезвия и направляют рукопожатие по маршруту имён.
Побочный эффект, имя сайта летит открытым текстом и его читают все
За решённую проблему хостинга пришлось заплатить неожиданным счётом. ClientHello, как вся начальная фаза, идёт по сети открытым текстом, потому что шифровать пока нечем - ключи ещё только согласовываются. Получается парадокс эпохи: содержимое страницы надёжно зашифровано, куки в безопасности, а сам факт посещения этого конкретного сайта виден любому устройству на маршруте. Наблюдатель не знает что́ вы читали, но знает куда зашли, и для многих задач этого достаточно.
Эту подсказку быстро взяли на вооружение. Каскады DPI у провайдеров научились выдёргивать поле server_name из первых пакетов соединения и сравнивать имя со списками фильтрации провайдером: подлинное имя совпало - рукопожатие рвётся сбросом или таймаутом, не совпало - соединение пропускается дальше. Так же работает корпоративная фильтрация: сервер посредник в периметре компании анализирует имена и кладёт правила доступа не на грубые адреса, а на точные хосты. Телеметрия операторов, оценка трафика, отладка приложений сетевыми инженерами - всё строится на том, что клиент любезно сообщает куда идёт.
Индустрия ответила приёмом по имени domain fronting: клиент называет в ClientHello безобидное имя, а внутри зашифрованного канала просит другой хост на той же ферме. Фокус работал на платформах, где фронт роутил по Host независимо от SNI. Платформы починили такое поведение, требуя совпадения имён.
Прячется сертификат, но не имя, от ESNI к зашифрованному ClientHello
TLS версии 1.3 внёс серьёзное усовершенствование приватности: сертификат сервера теперь передаётся уже под шифром рукопожатия, и пассивный наблюдатель больше не видит его содержимого. Инженеры праздновали, но честный взгляд показывал дыру: имя клиента в server_name по-прежнему летит в чистом виде, потому что зашифровать его значит спрятать от самого сервера, который должен по этому имени выбирать сертификат. Классическая замкнутость: чтобы спрятать указатель, нужен путь, который уже отрыт по другому указателю.
Первая волна решений называлась ESNI, Encrypted SNI. Идея привлекательная: оператор фермы публикует в DNS свой публичный ключ, клиент перед рукопожатием забирает этот ключ и шифрует им имя настоящего сайта, а снаружи подкладывает имя-прикрытие из той же фермы. Сервер на входе расшифровывает внутреннюю запись и выбирает правильный сертификат; наблюдатель видит только внешнее имя и тёмную массу байт. Практика показала слабые места: шифровалось только одно поле, остальное ClientHello несло характерные отпечатки, а при сбое механизма возникали вопросы деградации.
На смену пришёл Encrypted ClientHello, сокращённо ECH. Теперь защищается не одно имя, а вся внутренняя копия приветственного сообщения, а снаружи остаётся приведённый в порядок внешний ClientHello с именем фасада. Ключ по-прежнему публикуется через DNS в новых записях HTTPS и SVCB, что красиво связывает анонс возможностей сервиса с самой зоной. Схема объявляет честную сделку: приватность достигается внутри больших ферм и CDN, где фронт один, а клиентов много, потому что анонимность работает против толпы соседей. Одинокий сайт с выделенным адресом от ECH не выигрывает: адрес сам выдаёт назначение. Так и складывается второй слой экономики - приватность у имени сайта становится не личной настройкой, а сервисом инфраструктуры, которую арендуют вместе с фронтом.
Экономика хостинга, виртуальные HTTPS-хосты, CDN-фермы и общие сертификаты
Последствия SNI для экономики стоит считать отдельно, настолько они объёмны. Первый эффект: цена защищённого сайта упала к цене обычного, и TLS перестал быть признаком солидности. Массовые панели стали выпускать сертификаты автоматом, Let s Encrypt стал возможен в таком масштабе именно потому, что один фронт-балансировщик мог обслуживать тысячи доменов без выделенных адресов. Второй эффект: выделенный IP из обязательного атрибута превратился в платную опцию «для старых клиентов», а потом и вовсе в музейный экспонат.
Третий эффект касается CDN. Платформы нацеливают на один фронт десятки тысяч имён, и SNI становится азбукой маршрутизации на границе: терминатор читает имя, выбирает сертификат, смотрит конфигурацию ровно этого заказчика, применяет его политику кэша и правила. Хозяйство держится на двух механизмах упаковки сертификатов. Wildcard закрывает все поддомены одного домена одним документом и удобен платформенным командам, которым выпускать отдельные сертификаты на каждый новый стенд накладно. Сертификаты с перечнем альтернативных имён SAN позволяют одному документу укрывать родственные сайты заказчика, но любое изменение списка требует перевыпуска и видно в прозрачных журналах, поэтому крупные операторы чаще складывают по одному сертификату на арендатора и доверяют SNI выбор между документами.
Заодно SNI стал границей управления. Политики безопасности, лямбды на границе, карты маршрутов, гео-ограничения - всё это привязано к имени из ClientHello, и перенастройка сводится к записи в конфигурации хоста, а не к движению адресов. Хостинг-провайдер продаёт по сути строки в таблице имён, а не числа из пула. Сам продукт это умение быстро и надёжно разрулить миллионы рукопожатий по имени, не перепутав ключи.
Диагностика в полевых условиях и границы применимости
Инженеру, который обслуживает такие фермы, SNI виден руками. Базовый инструмент выглядит так:
- openssl s_client -connect адрес:443 -servername имя показывает, какой сертификат отдаст сервер на конкретное имя, и помогает отличать ошибку таблицы виртуальных хостов от ошибки самого сертификата;
- openssl s_client без параметра -servername демонстрирует сертификат по умолчанию, и сравнение двух прогонов мгновенно доказывает или опровергает гипотезу про SNI;
- curl с --resolve и с указанием хоста в URL проверяет всю связку, включая поведение уровня HTTP после выбора сертификата;
- захват трафика через tcpdump или Wireshark позволяет раскрыть ClientHello и увидеть поле server_name своими глазами, что неоценимо при спорах о том, шлёт ли клиент имя вообще.
Практика диагностики укладывается в несколько сюжетов. Самый частый: клиент подключился по голому IP и получил чужой сайт. Это не поломка, а следствие архитектуры: при отсутствии имени сервер показывает сертификат и содержимое по умолчанию, а если политика строгая, просто обрывает. Сайт за SNI по голому адресу недоступен, если оператор не выбрал показывать default, и это осознанная граница защиты. Второй сюжет: старое устройство или библиотека не посылает расширение, и поддержка полдня ищет неисправность на сервере, хотя неисправность живёт на клиенте. Третий сюжет: сертификат правильный, имя правильное, но таблица маршрутизации на балансировщике ссылается на соседний пул, и тогда помогает только чтение имени в захвате и сличение с конфигурацией фронта.
Отдельный навык - различать сбой фильтрации от сбоя сервиса. Обрыв сразу после ClientHello при том, что с другого маршрута сайт отвечает, обычно говорит: имя проанализировано на пути и рукопожатие сброшено.
Итог для платформенной практики
SNI это пример того, как одно поле в приветственном сообщении меняет экономику отрасли. Оно сняло искусственный предел один адрес один сертификат, сделало HTTPS массовым, превратило хостинг в таблицу имён и подарило CDN удобный крючок маршрутизации. Но оно же вывесило приватности наружу: имя сайта читает любой на маршруте, на этом построены системы ограничения, и индустрии пришлось десятилетие работать над тем, чтобы упрятать содержимое приветствия через DNS-ключи и ECH. Платформенный инженер, понимающий эту механику, смотрит на ClientHello не как на тайный ритуал криптографии, а как на документ, в котором одна строка продолжает решать судьбу соединения, как и двадцать лет назад, когда расширение только появилось.