Безопасность серверов

Ошибки SSL/TLS-сертификатов: expired, chain incomplete и mismatch

Как диагностировать ошибки проверки TLS-сертификата по данным реального endpoint: сроку действия, SAN, цепочке, trust store, отзыву и ключу.

9 минут
абстрактная иллюстрация проверки цепочки TLS-сертификатов
Данные локального файла не доказывают, что этот же сертификат видят пользователи: между ними могут быть виртуальный хост, reverse proxy, балансировщик или CDN.
Ошибку TLS нужно разбирать по тому, какой сертификат TLS и какую цепочку сервер фактически отдаёт на нужном имени и порту. Проверьте даты, имя в Subject Alternative Name, передаваемые промежуточные сертификаты и результат проверки с хранилищем доверия целевого клиента. Несоответствие локального сертификата закрытому ключу — отдельная серверная проблема: она обычно мешает загрузить TLS-конфигурацию или завершить handshake до проверки доверия клиентом.

Сначала зафиксируйте условия ошибки

До изменения файлов сохраните точный текст ошибки, DNS-имя, порт, время события с часовым поясом, тип клиента и его версию. Сообщение certificate verify failed само по себе недостаточно: его могут вызвать срок действия, имя, недоверенный CA, неполная цепочка или проверка отзыва.

  • Имя должно быть именно тем, к которому подключается клиент: api.example.com и example.com — разные проверки.
  • Укажите порт сервиса. TLS может завершаться не только на 443, но и на почтовом, административном или внутреннем endpoint.
  • Зафиксируйте, где произошла проверка: браузер, Java-приложение, почтовый клиент, агент мониторинга и ОС могут использовать разные хранилища доверенных сертификатов и политику отзыва.
  • Проверьте время именно на клиенте, который отклонил соединение. В контейнере, виртуальной машине или устройстве оно может отличаться от времени на сервере.

О версиях и документации

Команды ниже ориентированы на документированные интерфейсы OpenSSL 1.1.1 и OpenSSL 3.x; доступные параметры и формат диагностики нужно сверять с openssl <команда> -help и руководством установленной версии. Названия директив сертификата, ключа, цепочки, reload и статусов зависят от TLS-терминатора, его версии, ОС и схемы установки. Для изменения конфигурации используйте официальное руководство именно вашего веб-сервера, почтового сервиса, балансировщика, CDN или приложения.

Диагностический маршрут: что сервер отдаёт на самом деле

Проверка публичного TLS-endpoint через OpenSSL

Используйте OpenSSL с тем же именем и портом, которые применяет проблемный клиент. Это проверяет доступный endpoint, а не файл сертификата на диске.

  1. 1
    Подключитесь с SNI
    Передайте имя через -servername. SNI позволяет серверу выбрать нужный виртуальный хост и сертификат до HTTP-запроса.
  2. 2
    Получите переданные сертификаты
    Опция -showcerts выводит сертификаты, присланные сервером. Сохраните вывод: первый сертификат обычно является сертификатом сервиса, следующие — кандидатами на промежуточные звенья цепочки.
  3. 3
    Проверьте имя и доверие отдельно
    Опция -verify_hostname задаёт имя для проверки имени хоста. -CAfile и -CApath задают доверенные CA для этой проверки; они не добавляют промежуточные сертификаты в ответ сервера. Для диагностического отказа при ошибке проверки добавьте -verify_return_error.
  4. 4
    Сопоставьте результат с клиентом
    Сравните Subject, SAN, Issuer, даты и список сертификатов с ожидаемыми. Успешный результат OpenSSL означает только успешную проверку в указанной конфигурации OpenSSL, а не идентичное поведение браузера, Java, почтового клиента или библиотеки приложения.
Подключается к `example.com:443`, передаёт SNI и выводит сертификаты, реально полученные от сервера. В строках `Certificate chain` и `Verify return code` ищите состав цепочки и результат проверки.
openssl s_client -connect example.com:443 -servername example.com -showcerts -verify_hostname example.com -verify_return_error </dev/null
Вывод:
При успешной проверке обычно будет `Verify return code: 0 (ok)`. Ненулевой код — основание проверить конкретную причину, а не отключать проверку.

Не отключайте проверку как «исправление»

Опции и настройки, игнорирующие ошибки сертификата, могут быть полезны только в строго изолированной диагностике. Они не исправляют expired, mismatch или недоверенную цепочку и создают риск подключения к подменённому endpoint.

Как посмотреть даты, Subject, Issuer, SAN и отпечаток PEM-сертификата

Файл PEM-сертификата можно изучить локально командой openssl x509. Она показывает содержимое одного сертификата, но не подтверждает, что его использует работающий сервис. Для DER-файла укажите -inform DER; формат файла и расширение не следует определять только по имени.

Показывает `notBefore` и `notAfter`, Subject, Issuer, расширение SAN и SHA-256-отпечаток локального PEM-сертификата. Сравнивайте его с первым сертификатом из `s_client`, если нужно доказать, что сервис загрузил именно этот файл.
openssl x509 -in server-cert.pem -noout -dates -subject -issuer -ext subjectAltName -fingerprint -sha256

Поле Subject полезно для идентификации, но проверка имени хоста опирается прежде всего на SAN. Отпечаток позволяет без передачи самого сертификата сопоставить экземпляры в конфигурации, журналах и на endpoint.

Certificate has expired: срок сертификата, часы клиента или другой виртуальный хост

Проблема

Ошибка certificate has expired или certificate is not yet valid

Возможные причины

  • Поле `Not After` у фактически предъявленного сертификата уже прошло.
  • Дата или системное время на проверяющем клиенте неверны; тогда действующий сертификат может выглядеть просроченным либо ещё не действующим. Часовой пояс важен для интерпретации журналов и ручной настройки часов, но при корректном абсолютном времени сам по себе обычно не меняет результат проверки.
  • Из-за отсутствующего или другого SNI сервер отдал сертификат другого виртуального хоста.
  • Просрочен не конечный, а промежуточный сертификат в пути, который строит клиент.

Решение

Сначала выполните openssl s_client с -servername, затем извлеките и проверьте даты первого и всех переданных сертификатов. Сверьте дату и системное время проблемного клиента с надёжным источником времени. Если с SNI выводится актуальный сертификат, а без него — другой, исправляйте выбор виртуального хоста или настройки клиента, который не передаёт SNI. Если просрочен действительно используемый сертификат, установите замену вместе с корректной цепочкой и примените конфигурацию способом, указанным в документации сервиса.

Как избежать

Контролируйте срок сертификата на внешнем endpoint и отдельно время на клиентских системах; проверка только файла в каталоге сертификатов не заменяет такой контроль.

Неверное время на сервере не меняет то, как удалённый клиент сравнивает даты уже предъявленного сертификата: клиент использует собственные часы. Однако время сервера может влиять на выпуск и продление сертификата, выбор сертификата приложением, журналы и работу OCSP stapling, поэтому его также следует синхронизировать и проверять отдельно.

Hostname mismatch: имя должно быть в SAN

Проблема

Ошибка hostname mismatch, ssl certificate mismatch или отказ проверки имени

Возможные причины

  • DNS-имя, к которому подключается клиент, отсутствует среди DNS-значений SAN.
  • Клиент подключается по IP-адресу, но в SAN нет соответствующего IP-значения.
  • Сервис отдал сертификат другого virtual host из-за неверного или отсутствующего SNI.
  • Клиент использует внутреннее имя, алиас или имя балансировщика, которое не было включено в сертификат.

Решение

Посмотрите SAN у сертификата, полученного с endpoint, и найдите точное имя подключения. Если имени нет, выпустите и установите сертификат с нужным SAN либо измените конфигурацию клиента на имя, которое уже корректно включено в SAN. Если сертификат правильный только при -servername example.com, настройте SNI у клиента или корректный default virtual host согласно документации TLS-терминатора.

Как избежать

Включайте в заявку на сертификат все реальные DNS-имена и IP-адреса, которыми пользуются клиенты, включая имена reverse proxy и внутренние endpoint.

Выводит SAN локального сертификата. Для расследования mismatch выполняйте ту же проверку над сертификатом, который был получен через `s_client`, а не только над файлом на сервере.
openssl x509 -in server-cert.pem -noout -ext subjectAltName

CN не заменяет SAN

Современная проверка имени хоста сопоставляет DNS-имя или IP-адрес прежде всего с SAN. Поле Common Name в Subject не следует использовать как основание считать сертификат подходящим, если нужного значения нет в SAN.

Chain incomplete и unable to verify certificate

Цепочка сертификатов должна связать конечный сертификат сервиса с доверенной точкой клиента. Частая причина chain incomplete — сервер не передаёт нужный промежуточный сертификат. Ошибку также вызывают промежуточный сертификат от другого выпуска CA и порядок сертификатов, не соответствующий формату конкретного TLS-терминатора. Лишние или не связанные с путём сертификаты могут мешать отдельным продуктам и клиентам, но одно их наличие ещё не доказывает причину отказа.

КомпонентРольГде должен находиться
Сертификат сервисаИдентифицирует endpoint и содержит его открытый ключПервым в серверной выдаче и в файле/настройке, если сервис ожидает объединённую цепочку
Промежуточный CAСвязывает сертификат сервиса с доверенным CAОбычно передаётся сервером после сертификата сервиса
Корневой сертификатТочка доверия клиентаОбычно находится в trust store клиента, а не передаётся сервером

Как проверить локальный сертификат и цепочку

Проверяет локальный сертификат `server-cert.pem`, используя корневые сертификаты из `trusted-roots.pem` как доверенные и промежуточные сертификаты из `intermediates.pem` как кандидатов для построения пути.
openssl verify -CAfile trusted-roots.pem -untrusted intermediates.pem server-cert.pem
Вывод:
Успешная проверка обычно выводит `server-cert.pem: OK`. Параметр `-untrusted` не делает промежуточные сертификаты доверенными точками: доверие должно завершаться сертификатом из указанного trust store. Ошибки `unable to get local issuer certificate` и `unable to get issuer certificate` требуют проверить состав промежуточных сертификатов и доверенных корней.

Проблема

Сервер отдаёт неполную цепочку или клиент не может построить путь доверия

Возможные причины

  • Изменён не тот компонент: TLS завершается на CDN, балансировщике, reverse proxy, почтовом шлюзе или другом фронтенде.
  • TLS-терминатор загрузил только конечный сертификат либо использует старый файл, секрет или объект конфигурации.
  • У клиента отсутствует подходящий доверенный корень или он строит другой путь сертификации.

Решение

Сравните SHA-256-отпечаток первого сертификата из s_client с сертификатами на каждом предполагаемом TLS-терминаторе. По схеме сервиса определите компонент, который принимает TLS-соединение на проверяемом имени и порту. Затем найдите в официальном руководстве именно его версии параметры конечного сертификата, цепочки и закрытого ключа, источник секрета и способ проверки конфигурации и reload. После изменения снова проверьте внешний endpoint: успешная локальная проверка файла не подтверждает, что этот файл загрузил обслуживающий соединение компонент.

Как избежать

Документируйте владельца TLS-терминации, источник сертификата и цепочки, способ применения конфигурации и проверяемый внешний endpoint.

Доверенный CA зависит от хранилища клиента

  • В Debian и Ubuntu локальный корневой CA в PEM-формате обычно помещают отдельным файлом с расширением .crt в /usr/local/share/ca-certificates/, после чего запускают update-ca-certificates.
  • В актуальных RHEL-совместимых системах локальный корневой CA обычно помещают в /etc/pki/ca-trust/source/anchors/, после чего запускают update-ca-trust.
  • Пути, команды и поддерживаемые форматы сверяйте с документацией семейства и версии ОС. Java, браузер, контейнер или само приложение могут использовать собственное хранилище и не принять CA, добавленный только в системное.
  • Корневой сертификат внутреннего CA распространяйте только по контролируемому каналу и только на нужные клиенты. Добавление корня означает доверие всем сертификатам, которые этот CA вправе выпускать.

Серверная цепочка не заменяет trust store

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

Ошибки проверки отзыва через OCSP и CRL

Запрашивает у сервера stapled OCSP-ответ и выводит его, если TLS-терминатор такой ответ передал.
openssl s_client -connect example.com:443 -servername example.com -status </dev/null
Вывод:
Отсутствие stapled-ответа не означает, что сертификат отозван или что целевой клиент обязательно отклонит соединение. Наличие ответа также не доказывает, что каждый клиент проверяет отзыв.
Проверяет локальный конечный сертификат с явно предоставленным CRL. Команда не воспроизводит автоматически сетевую политику OCSP или CRL конкретного браузера, Java-приложения либо почтового клиента.
openssl verify -CAfile trusted-roots.pem -untrusted intermediates.pem -CRLfile issuer.crl -crl_check server-cert.pem
Вывод:
Сообщения наподобие `certificate revoked`, `unable to get certificate CRL` и ошибок срока CRL нужно отличать от ошибок имени, срока сертификата и построения цепочки.

Проблема

Клиент сообщает об ошибке OCSP, CRL или статуса отзыва

Возможные причины

  • Сертификат действительно отмечен CA как отозванный.
  • OCSP-ответ или CRL просрочен, недоступен либо не может быть проверен.
  • TLS-терминатор передаёт отсутствующий, старый или некорректный stapled OCSP-ответ.
  • Клиент настроен на fail-closed, тогда как другой клиент при той же недоступности службы отзыва продолжает соединение.

Решение

Проверьте точное сообщение и политику отзыва проблемного клиента, URI OCSP и CRL в сертификате, а также результат s_client -status. Если сертификат отозван, замените его по процедуре CA. Если проблема относится к stapling, исправьте получение и обновление ответа на фактическом TLS-терминаторе. Не делайте вывод о политике браузера или приложения только по результату OpenSSL: автоматическое получение данных, кэширование и режим fail-open или fail-closed зависят от клиента и TLS-библиотеки.

Как избежать

Контролируйте срок действия stapled OCSP-ответов и доступность используемых источников статуса с учётом политики реальных клиентов.

Как проверить соответствие сертификата закрытому ключу

Извлекает открытый ключ из сертификата, приводит его к DER и вычисляет SHA-256-хеш. Способ применим не только к RSA, но и к поддерживаемым `openssl pkey` типам ключей, включая EC.
openssl x509 -in server-cert.pem -pubkey -noout | openssl pkey -pubin -outform DER | openssl dgst -sha256
Извлекает соответствующий открытый ключ из закрытого ключа и вычисляет хеш в том же формате.
openssl pkey -in server-key.pem -pubout -outform DER | openssl dgst -sha256
Вывод:
Одинаковые хеши означают, что сертификат и закрытый ключ содержат одну пару открытого и закрытого ключей. Разные хеши указывают на несоответствие файлов.

Несоответствие пары обычно проявляется при проверке или загрузке конфигурации TLS-терминатором либо при handshake; это не ошибка построения клиентом цепочки доверия. Закрытый ключ должен быть доступен учётной записи или механизму секретов, от имени которого продукт читает его, но недоступен посторонним пользователям. Не назначайте универсальный режим вроде chmod 600 без проверки модели запуска: владелец, группа, права каталогов, контейнерное монтирование и менеджер секретов зависят от ОС и сервиса. Требования сверяйте с официальной документацией продукта и его версии.

Термины в статье

OCSP — сетевой протокол для запроса статуса отдельного X.509-сертификата у OCSP-респондера без загрузки списка отозванных сертификатов (CRL).
OpenSSL — программная криптографическая библиотека и набор утилит для реализации TLS, управления сертификатами, ключами, хешированием и другими криптографическими операциями.
PEM — текстовый формат представления криптографических объектов в Base64 между строками BEGIN/END с меткой типа объекта; он не задаёт алгоритм шифрования или тип ключа.
SNI — расширение TLS, в котором клиент передаёт имя целевого хоста в ClientHello, позволяя серверу выбрать сертификат и TLS-конфигурацию до HTTP-запроса.
SSL — устаревшее семейство протоколов защиты сетевых соединений, предшествующее TLS; версии SSL 2.0 и SSL 3.0 не следует включать в рабочих конфигурациях.
Subject Alternative Name — расширение X.509-сертификата, содержащее DNS-имена, IP-адреса, URI и другие идентификаторы, с которыми связывается открытый ключ.
TLS — криптографический протокол защиты прикладных данных при передаче по сети, обеспечивающий их конфиденциальность и целостность, а также аутентификацию сервера и, при настройке, клиента.
Закрытый ключ — секретная часть асимметричной ключевой пары для создания подписей, расшифрования данных или подтверждения владения ключом при аутентификации.
Корневой сертификат — самоподписанный сертификат центра сертификации, служащий верхней точкой доверия при проверке цепочек сертификатов.
Отзыв сертификата — прекращение доверия к действующему сертификату до истечения его срока, фиксируемое центром сертификации в CRL или через OCSP.
Открытый ключ — несекретный ключ асимметричной пары, используемый в зависимости от алгоритма для проверки подписей, шифрования, аутентификации или согласования общего секрета.
Проверка имени хоста — этап валидации TLS-сертификата, при котором имя целевого узла сопоставляется с DNS-именем или IP-адресом в SAN сертификата.
Промежуточный сертификат — подписанный вышестоящим CA сертификат подчинённого центра, чей открытый ключ используется для проверки выпущенных им сертификатов в цепочке доверия.
Сертификат TLS — цифровой документ X.509, содержащий открытый ключ и идентификаторы субъекта и подписанный издателем; доверие к связи определяется цепочкой и политикой клиента.
Сертификат X.509 — цифровой документ стандартизированного формата, связывающий открытый ключ с субъектом и подписанный издателем: центром сертификации или самим субъектом.
Список отзыва сертификатов — подписанный издателем CRL перечень сертификатов, признанных недействительными до истечения срока их действия.
Срок действия сертификата — интервал между полями Not Before и Not After, в пределах которого сертификат может считаться действующим при успешной проверке остальных условий.
Хранилище доверенных сертификатов — набор сертификатов и правил доверия, используемый системой или приложением при проверке цепочек сертификатов и цифровых подписей.
Центр сертификации — доверенная организация или сервис PKI, выпускающий и подписывающий сертификаты, чтобы связать открытые ключи с проверенными идентификаторами субъектов.
Цепочка сертификатов — последовательность от конечного сертификата через сертификаты центров сертификации к точке доверия, позволяющая проверить подписи и построить путь доверия.

Вопросы по теме

Все вопросы и ответы

Как проверить сертификат через openssl s_client?

Команда для проверки публичного endpoint: openssl s_client -connect example.com:443 -servername example.com -showcerts -verify_hostname example.com -verify_return_error </dev/null.

Параметр -servername передаёт SNI, поэтому сервер выбирает сертификат нужного виртуального хоста до HTTP-запроса. Без него можно получить сертификат другого сайта и сделать неверный вывод. -showcerts выводит переданную цепочку: первый сертификат обычно принадлежит сервису, следующие являются промежуточными. -verify_hostname проверяет имя подключения, а -verify_return_error делает диагностическую ошибку явной.

При необходимости можно указать -CAfile или -CApath для конкретного набора доверенных CA. Эти параметры влияют на проверку OpenSSL, но не добавляют промежуточные сертификаты в выдачу сервера. Успех команды подтверждает проверку только в выбранной конфигурации OpenSSL: браузер, Java-приложение или почтовый клиент могут использовать другое хранилище доверия и другую политику отзыва.

Нужно ли отправлять корневой сертификат в серверной цепочке?

Обычно нет. Корневой сертификат должен находиться в trust store клиента, а сервер обычно передаёт сертификат сервиса и необходимые промежуточные CA. Передача корня сама по себе не делает его доверенным. Лишние или не связанные с путём сертификаты могут мешать отдельным клиентам, поэтому состав цепочки нужно проверять на реальном endpoint.

Почему клиент не доверяет CA после обновления корневых сертификатов Linux?

Потому что обновление системного trust store может не затрагивать хранилище конкретного клиента. Java, браузер, контейнер или само приложение способны использовать собственный набор доверенных CA. На Debian и Ubuntu обычно используют .crt в /usr/local/share/ca-certificates/ и update-ca-certificates; на RHEL-совместимых системах — anchors и update-ca-trust. Затем проверяйте именно проблемным клиентом.

Как проверить, совпадает ли SSL-сертификат с закрытым ключом?

Сравните SHA-256-хеши открытых ключей, извлечённых из сертификата и закрытого ключа. Для сертификата используйте openssl x509 -pubkey, для ключа — openssl pkey -pubout, в обоих случаях с DER и openssl dgst -sha256. Одинаковые хеши означают совпадение пары. Несовпадение обычно мешает загрузке TLS-конфигурации или handshake.

Может ли неверное время сервера вызвать ошибку у удалённого клиента?

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

Что проверять при ошибке certificate revocation check failed?

Проверьте точный текст ошибки, политику отзыва проблемного клиента, URI OCSP и CRL в сертификате, а также stapled OCSP-ответ через openssl s_client -status. Причиной может быть настоящий отзыв сертификата, недоступный или просроченный OCSP/CRL либо некорректный stapling на TLS-терминаторе. Поведение зависит от того, работает ли клиент в режиме fail-open или fail-closed.