Кто-то говорит вам, что ваш сайт небезопасен. Вы его открываете: замочек, нет предупреждений, сертификат действителен еще четыре месяца. Вы просите их попробовать еще раз, и это все еще не работает, в сети, до которой вы не можете добраться, в клиенте, который у вас нет.

Ни один из вас не ошибается, и сертификат не является проблемой. Различие в том, что находится под ним.

Сертификат не является надежным сам по себе

Ваш сертификат не утверждает, что он является надежным. Он подписан промежуточным сертификатом, который подписан корневым, и только корневой находится в хранилище доверия посетителя. Задача во время подключения состоит в том, чтобы построить этот путь, а задача вашего сервера состоит в том, чтобы передать середину этого пути.

TLS 1.3 определяет, что отправляет сервер, и формулировка стоит внимательного прочтения:

certificate_list: последовательность (цепь) структур CertificateEntry, каждая содержит один сертификат и набор расширений.

А затем следует правило, которое обычно пропускается:

Сертификат отправителя ДОЛЖЕН быть в первой CertificateEntry в списке. Каждый последующий сертификат ДОЛЖЕН напрямую удостоверять предыдущий. Поскольку проверка сертификата требует независимого распределения якорей доверия, сертификат, указывающий якорь доверия, МОЖЕТ быть опущен из цепи, при условии, что известно, что поддерживаемые узлы обладают всеми опущенными сертификатами.

Внимательно прочитайте последнее предложение. Якорь доверия, то есть корневой сертификат, может быть опущен, потому что клиенты его уже имеют. Это не оправдывает пропуск промежуточного сертификата. Ваш сервер должен отправлять все, что находится между вашим сертификатом и корневым, а промежуточный сертификат это и есть.

Неправильную конфигурацию, которую вы никогда не заметите сами

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

Mozilla описала отсутствие правильных промежуточных сертификатов ЦА как “одну из наиболее распространенных проблем конфигурации сервера” и предприняла меры: Firefox предварительно загружает промежуточные сертификаты ЦА, в список, который “содержит более двух тысяч записей”, специально чтобы снизить “ошибки неизвестного издателя в процессе TLS handshake”.

Задумайтесь о том, что это значит. Браузеры активно компенсируют эту ошибку. Браузер, который уже имеет промежуточный сертификат, установит соединение независимо от того, отправил ли его ваш сервер или нет, поэтому ваш собственный тест проходит и неправильная конфигурация остается незаметной. Компенсация это хорошая инженерия и это также причина, по которой никто это не замечает.

Почему один клиент не работает, а другой работает

Существует второй механизм, который это скрывает, и он исходит из самого сертификата.

Сертификат может указывать, где можно найти сертификат его издателя. RFC 5280 определяет это поле и осторожно описывает его назначение:

id-ad-caIssuers OID используется, когда дополнительная информация содержит список сертификатов, выданных ЦА, которая выдала сертификат, содержащий это расширение. Описание указанных издателей ЦА предназначено для помощи пользователям сертификатов при выборе пути сертификации

“Предназначено для помощи” - это ключевая фраза. Это указатель, а не обязательство. Клиент может следовать этому и получить недостающий элемент, а может отказаться. Оба варианта соответствуют стандарту.

Спецификация TLS столь же откровенна о состоянии дел, отмечая, что серверы иногда отправляют дополнительные или неправильно упорядоченные сертификаты и что “другие просто неправильно настроены”, прося реализации быть терпимыми.

Что вы тестировали
Современный браузер для настольных ПК, который предварительно загружает тысячи промежуточных сертификатов и будет получать отсутствующего издателя, если потребуется. Самый терпимый клиент из ваших
Что использовал ваш посетитель
Что-то более строгое или старое, которое проверяет только то, что ему было дано, и сообщает об неизвестном издателе, когда цепь не доходит до корневого сертификата

Таким образом, терпимость это решение клиента, а не свойство вашей конфигурации, и вы тестировали с клиентом, который с наибольшей вероятностью вас простит.

Отчеты, которые это фактически генерирует

Поскольку терпимые клиенты это браузеры, сбои происходят в другом месте, и они редко приходят описанными как проблема с сертификатом.

  • Webhook перестает доставляться. Теперь клиентом является сервер кого-то другого, и у него нет предварительно загруженного списка и нет интереса к получению вашего издателя.
  • Мобильное приложение не может выполнить вход, а тот же аккаунт работает в интернете, потому что сетевой стек приложения отличается от системного браузера.
  • Интеграция платежей или доставки не работает с вашим URL обратного вызова, обычно с сообщением об неизвестном или ненадежном издателе.
  • Один офис или одно старое устройство вообще не может получить доступ к сайту, а все остальные могут.

Ни один из них не звучит как “цепь сертификатов неполная”, поэтому часы идут в неправильное место в первую очередь.

Промежуточный сертификат это единица зоны поражения

Еще одна причина узнать, от какого промежуточного сертификата вы зависите, отдельно от того, отправляете ли вы его.

Промежуточный сертификат подписывает множество сертификатов. Если один из них отозван, не доверяется или истекает, каждый сертификат под ним перестает проверяться в один и тот же момент. Ваш сертификат может быть в нескольких месяцах от собственного истечения, неизменный, и все равно не пройти проверку, потому что то, что сломалось, это одна ссылка выше и это было не ваше.

Большинство систем мониторинга сертификатов отслеживают одну дату: когда истекает ваш сертификат. Это правильная дата для отслеживания, и это не единственная, и другая принадлежит сертификату, который вы не выбирали и, вероятно, не можете назвать.

Проверка занимает около тридцати секунд

Спросите сервер, что он фактически отправляет, от чего-то, что не является вашим браузером:

openssl s_client -showcerts -connect example.com:443 -servername example.com </dev/null

Две вещи для чтения в выводе. Подсчитайте сертификаты: типичная публичная цепь передает ваш сертификат и по крайней мере один промежуточный, поэтому ровно один сертификат это классический симптом этой ошибки. Затем прочитайте issuer вашего сертификата и проверьте, что сертификат с subject присутствует дальше.

Session Replay

Бесплатное расширение Chrome. Один клик на странице, которая ведет себя неправильно, захватывает скриншот, консоль и журнал сети, и дает вам ссылку для вставки в тикет.

Получить расширение

Если вместо этого вы получите скриншот экрана с предупреждением, пять различных ошибок за этой одной страницей стоит разделить перед началом: ваше соединение не является приватным.

Выводы из этого

Сертификат это ссылка, а не учетные данные. Он доверяется потому, что можно построить путь от него к чему-то, чему посетитель уже доверяет, и ваш сервер несет ответственность за середину этого пути.

Режим отказа необычайно жестокий, потому что компенсация так хороша. Браузеры предварительно загружают тысячи промежуточных сертификатов и будут искать отсутствующего издателя, поэтому клиент, с которым вы тестируете, это клиент, наименее вероятный вам это сказать. Те, которые вам говорят, это вебхуки, мобильные приложения и интеграции платежей, и они говорят вам словами, которые никогда не упоминают сертификаты.

Спецификации это RFC 8446 для того, что должен отправлять сервер, и RFC 5280 для поля, которое указывает местоположение издателя.