Кратко

  • TLS server_name — переданное клиентом DNS-имя в ClientHello, которое помогает заранее выбрать контекст, сертификат или адрес прозрачной пересылки. Это не удостоверение клиента.
  • Проверка сервисной идентичности, HTTP Host/:authority, upstream SNI, состояния ECH и прикладные права требуют отдельных решений, даже если значения строк совпадают.

Когда безошибочный выбор создал ложного субъекта

Callback получил ожидаемое имя, переключил SSL_CTX, а сервер предъявил правильный сертификат. Все показатели TLS были зелёными. Ошибка находилась после них: метка выбранной конфигурации стала tenant principal.

SNI нужен серверу виртуального хостинга до отправки сертификата. Клиент сообщает, какой сервис он хочет получить. Любой клиент, способный сформировать ClientHello, способен поставить туда допустимое имя — в том числе имя самого привилегированного tenant.

Выбранный сертификат позволяет проверяющему клиенту аутентифицировать сервер. Он не аутентифицирует клиента перед сервером. Система незаметно превратила полезный селектор в полномочие.

Формат не подтверждает право на имя

RFC 6066 определяет ServerNameList в ClientHello. Стандартизованный host_name — DNS-имя в ASCII; буквальные IPv4 и IPv6 запрещены, одинаковый тип имени нельзя повторять.

Эти правила уменьшают неоднозначность разбора. Они не подтверждают DNS-разрешение, контроль зоны, владение ключом, договор с tenant или право читать его данные. Инструмент может подключиться к заданному IP и отправить другое имя. Для атакующего это столь же просто.

Сервер может завершить соединение фатальным unrecognized_name, если понимает, но не принимает имя. Он может продолжить по заранее определённой fallback-политике. Поэтому отсутствие SNI, неизвестное имя и default virtual host нужно проверять на исполняемой системе, а не выводить из конфигурационной таблицы.

Целостность transcript не создаёт владение

В TLS 1.3 ClientHello входит в transcript, который в конце аутентифицируется Finished. Успешный handshake означает, что обычное SNI не было незаметно изменено посредником между endpoints.

Но это целостность заявления, а не полномочие заявителя. Сервер знает: именно этот клиент запросил имя в этой связи. Он не знает, контролирует ли клиент домен или действует ли от имени его оператора.

Без client certificate или иной аутентификации корректный TLS может оставить клиента анонимным. Сертификат сервера направлен в обратную сторону. Поэтому поле следует называть client_requested_server_name, а не verified_tenant.

Выбор сертификата не равен его проверке

SNI помогает серверу выбрать credential. RFC 9525 требует, чтобы клиент независимо построил приемлемые reference identifiers и сопоставил их с identifiers, предъявленными в сертификате.

Цепочка, срок действия, отзыв и совпадение сервисного имени принадлежат проверяющей стороне. Правильный выбор сервера не доказывает, что клиент выполнил эти действия.

OpenSSL также разделяет шаги. SSL_set_tlsext_host_name() задаёт SNI, а ожидаемое DNS-имя для проверки сертификата настраивается отдельно. Только первый вызов может получить нужный сертификат, не обеспечив строгую аутентификацию сервиса.

Один сертификат может легитимно содержать SAN для нескольких имён. Общая криптографическая оболочка не объединяет их tenant-права.

HTTP сообщает другую authority

После TLS HTTP/1.1 передаёт Host, а HTTP/2 и HTTP/3 обычно используют :authority. RFC 9110 относит эту информацию к критической для определения цели запроса.

Обычный клиент часто выводит SNI и HTTP authority из одной URI, поэтому строки совпадают. Это не связь протокольных полномочий. Повторное использование соединения, proxy, тест, ошибка или атака могут развести их.

Сервису нужна явная политика расхождения: отказ, маленькая документированная матрица или 421, если соединение не подходит origin. Первый SNI не должен молча разрешать все последующие authority.

Даже совпадение подтверждает лишь согласованность двух указаний назначения. Идентичность клиента и право операции остаются отдельными.

За TLS-терминатором начинается новая история

Терминирующий proxy завершает downstream handshake и создаёт отдельный upstream. У каждого свои ClientHello, SNI, сертификат, reference identity и результат.

Upstream SNI может быть фиксированным, происходить от upstream host, downstream HTTP authority или управляемого отображения. Envoy разделяет эти источники и отдельно задаёт SAN-проверку по фактическому SNI либо по request authority.

В passthrough-модели доказательство уже. NGINX ssl_preread читает SNI и выбирает backend без завершения TLS. Он может засвидетельствовать разбор подсказки и маршрут, но не проверку конечного сертификата или завершение handshake.

Одно поле sni стирает соединение, источник и проверяющую сторону. Корреляция может связать два участка, но не объединить их результаты.

ECH разделяет внутреннее и публичное имя

Encrypted Client Hello помещает чувствительные параметры в ClientHelloInner. ClientHelloOuter обычно содержит public name фронта, необходимое для маршрута и retry.

При принятии ECH обработка идёт по аутентифицированному inner. При отклонении соединение, аутентифицированное для public name, служит только получению данных повтора. RFC 9849 запрещает считать его успешной связью с origin.

Таким образом, outer SNI может быть правильным маршрутом и намеренно недостаточной origin-идентичностью. Телеметрия должна хранить ECH status, роль наблюдателя и источник имени, не смешивая ordinary, outer и accepted inner.

Распространение inner-имени тоже следует ограничить. Иначе мониторинг восстановит открытый реестр назначений, от которого ECH защищает сеть.

Проверять отказ, а не наличие callback

Первый тест отправляет SNI привилегированного tenant без client credential. Сертификат можно выбрать, TLS может завершиться, но principal обязан остаться анонимным, а административное действие — быть отклонено.

Затем проверяются отсутствие SNI, неизвестное имя, fallback, несовпадающая HTTP authority и сертификат, валидный для обоих имён. На proxy задаётся другое upstream SNI и требуются два результата проверки. Passthrough не должен объявлять TLS success. ECH проходит сценарии принятия, отклонения/retry и отсутствия.

API OpenSSL или GnuTLS показывает возможность. Реакция исполняемого кода на эти враждебные случаи показывает действующую границу.