Перейти к основному содержимому

Инспекция и проверка сертификатов

Компоненты Netgap аутентифицируют друг друга по mTLS, а трафик между шлюзами шифруется TLS 1.3. Любая ошибка в сертификате — истекший срок, не тот корень, отсутствующее расширение — приводит к обрыву соединения на этапе handshake, причем TLS-стек rustls сообщает о проблеме довольно лаконично. Поэтому перед тем как «скармливать» сертификат шлюзу, его нужно уметь инспектировать глазами. Эта статья — практический справочник команд OpenSSL для просмотра и проверки сертификатов, запросов на подпись (CSR) и пар «сертификат/ключ». Как эти файлы выпускаются на тестовом стенде — см. Выпуск сертификатов через OpenSSL, теория цепочки доверия — в статье Цепочка доверия.

1. Полный дамп сертификата

Максимально подробный, человекочитаемый вывод всего содержимого сертификата:

openssl x509 -in ca.crt -text -noout

Флаг -noout подавляет вывод самого PEM-блока (base64), оставляя только расшифровку. На что смотреть в выводе (на примере корневого сертификата нашей PKI):

ПолеЧто проверить
SubjectИмя владельца, например CN=cluster.local — домен доверия вашей PKI
ValidityNot Before / Not After — окно действия (для корня, выпущенного с -days 3650, это ровно 10 лет)
Public Key AlgorithmАлгоритм ключа, например ED25519 — см. Ключи и алгоритмы
X509v3 Basic Constraints: criticalДля корня обязательно CA:TRUE — только с этим флагом сертификат может подписывать другие сертификаты
X509v3 Key Usage: criticalДля корня — Certificate Sign, CRL Sign; для конечного (leaf) сертификата — Digital Signature
X509v3 Subject Alternative NameДля leaf-сертификата — DNS-имена/IP, по которым клиент будет сверять хост
Отсутствие CA:TRUE — фатально

Если в корневом сертификате нет Basic Constraints: critical, CA:TRUE, современные библиотеки (включая rustls) откажутся использовать его как доверенный корень, даже если подпись математически верна.

2. Компактный просмотр: subject, issuer, даты

Когда не хочется листать «простыню» полного дампа, основные метаданные можно запросить точечно:

openssl x509 -in ca.crt -subject -issuer -dates -noout
# subject=CN=cluster.local
# issuer=CN=cluster.local
# notBefore=Aug 7 10:00:00 2026 GMT
# notAfter=Aug 5 10:00:00 2036 GMT
Признак самоподписанного корня

Если subject и issuer полностью совпадают — перед вами самоподписанный сертификат. Для корневого CA это норма (он сам себе издатель), а вот leaf-сертификат сервиса с совпадающими полями — признак того, что его забыли подписать корнем.

3. Проверка назначения: -purpose

OpenSSL умеет выполнять «мини-тест» сертификата и отвечать, для каких ролей он пригоден:

openssl x509 -in ca.crt -purpose -noout
# Certificate purposes:
# SSL client : No
# SSL client CA : Yes
# SSL server : No
# SSL server CA : Yes
# ...
# CRL signing : Yes
# CRL signing CA : Yes

Как читать этот вывод:

  • SSL client CA : Yes — сертификат имеет право подписывать и выпускать клиентские сертификаты (то, что нужно для mTLS);
  • SSL server CA : Yes — имеет право выпускать серверные сертификаты (TLS/HTTPS);
  • CRL signing : Yes — может подписывать списки отзыва сертификатов, см. Отзыв сертификатов;
  • SSL client : No и SSL server : No — сам файл ca.crt нельзя использовать как конечный сертификат клиента или сервера: он только подписывает чужие.

У leaf-сертификата картина должна быть зеркальной: SSL server : Yes (или SSL client : Yes), а все строки ... CANo.

4. Инспекция CSR (запроса на подпись)

Для запроса на подпись сертификата (CSR — Certificate Signing Request) используется модуль req вместо x509:

openssl req -in mc_1_srv.csr -text -noout
# Certificate Request:
# Data:
# Version: 1 (0x0)
# Subject: CN=mc-1-srv
# Subject Public Key Info:
# Public Key Algorithm: ED25519
# Attributes:
# (none)
# Signature Algorithm: ED25519

Здесь стоит убедиться, что Subject содержит ожидаемое имя сервиса (см. Идентичность клиента) и что алгоритм ключа соответствует политике проекта. CSR подписан приватным ключом заявителя — эту самоподпись можно проверить, не подписывая сертификат:

openssl req -in mc_1_srv.csr -verify -noout
# Certificate request self-signature verify OK

Ошибка на этом шаге означает, что CSR поврежден при передаче или не соответствует ключу — подписывать его бессмысленно.

5. Проверка валидности сертификата

Цепочка доверия

Главная проверка: действительно ли указанный корень подписал этот сертификат и не истек ли срок действия:

openssl verify -CAfile ca.crt mc_1_srv.crt

Типовые ответы:

ВыводЧто это значит
mc_1_srv.crt: OKСертификат валиден: подпись цепочки подтверждена, даты в порядке
certificate has expiredНаступила дата Not After — сертификат истек, нужен перевыпуск
unable to get local issuer certificateПодпись не сходится с переданным ca.crt: указан не тот корень либо в цепочке не хватает промежуточного сертификата

Быстрая проверка срока действия

Проверить только даты, без криптографии:

# Действует ли сертификат прямо сейчас (exit code 0 = да)
openssl x509 -in mc_1_srv.crt -checkend 0

# Истечет ли сертификат в ближайшие 30 дней (2592000 секунд)
openssl x509 -in mc_1_srv.crt -checkend 2592000

Команда -checkend N отвечает на вопрос «будет ли сертификат действителен через N секунд» и удобна в скриптах мониторинга: ненулевой код возврата — сигнал к ротации, см. Автоматизация выпуска.

Соответствие пары сертификат/ключ

Чтобы убедиться, что mc_1_srv.crt и mc_1_srv.key — действительно одна пара, сравните sha256-дайджесты их публичных ключей:

openssl x509 -noout -pubkey -in mc_1_srv.crt | openssl pkey -pubin -outform DER | openssl dgst -sha256
openssl pkey -in mc_1_srv.key -pubout -outform DER | openssl dgst -sha256

Если хеши совпали — пара верна. Способ универсален и работает в том числе для Ed25519.

примечание

Для старых RSA-ключей часто советуют сравнивать модули через openssl x509 -modulus, но у Ed25519 модуля нет — для современных ключей приведенный выше вариант с -pubkey является единственным рабочим.

6. Как это проверяет rustls

Netgap использует rustls, и во время handshake библиотека автоматически повторяет те же проверки, что вы делали руками:

  1. Подпись цепочки — криптографическая подпись предъявленного сертификата проверяется вплоть до корня, добавленного в RootCertStore (аналог openssl verify -CAfile);
  2. Окно действия — rustls берет системное время машины и сравнивает его с Not Before / Not After. Уехавшие системные часы — частая причина «внезапно невалидных» сертификатов;
  3. Назначение (EKU) — TLS-клиент требует у сертификата сервера расширение serverAuth, сервер у клиента — clientAuth. Если у сервера прописан только clientAuth, rustls оборвет соединение с ошибкой вида InvalidCertificate;
  4. Имя хоста — клиент сверяет домен, к которому подключается (например, mc-1-srv.local), со списком в Subject Alternative Name сертификата сервера.

Подробности настройки клиента и сервера — в статье mTLS на rustls.

7. Шпаргалка команд

ЗадачаКоманда
Полный дамп сертификатаopenssl x509 -in cert.crt -text -noout
Кратко: subject, issuer, датыopenssl x509 -in cert.crt -subject -issuer -dates -noout
Назначения сертификатаopenssl x509 -in cert.crt -purpose -noout
Дамп CSRopenssl req -in req.csr -text -noout
Проверка самоподписи CSRopenssl req -in req.csr -verify -noout
Проверка цепочки доверияopenssl verify -CAfile ca.crt leaf.crt
Действует ли сейчасopenssl x509 -in cert.crt -checkend 0
Истечет ли за 30 днейopenssl x509 -in cert.crt -checkend 2592000
Дайджест публичного ключа сертификатаopenssl x509 -noout -pubkey -in cert.crt | openssl pkey -pubin -outform DER | openssl dgst -sha256
Дайджест публичного ключа из приватногоopenssl pkey -in key.key -pubout -outform DER | openssl dgst -sha256

Перед вводом сертификата в эксплуатацию имеет смысл пройтись по всем разделам этой шпаргалки: просмотреть полный дамп (Subject, Validity, расширения), убедиться в наличии CA:TRUE у корня и правильных ролей у leaf через -purpose, проверить цепочку openssl verify именно с тем корнем, который стоит у клиентов, сверить SAN со всеми именами подключения и убедиться, что пара «сертификат/ключ» совпадает по дайджестам.