Инспекция и проверка сертификатов
Компоненты 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 |
Validity | Not 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, по которым клиент будет сверять хост |
Если в корневом сертификате нет 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), а все строки ... CA — No.
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 библиотека автоматически повторяет те же проверки, что вы делали руками:
- Подпись цепочки — криптографическая подпись предъявленного сертификата проверяется вплоть до корня, добавленного в
RootCertStore(аналогopenssl verify -CAfile); - Окно действия — rustls берет системное время машины и сравнивает его с
Not Before/Not After. Уехавшие системные часы — частая причина «внезапно невалидных» сертификатов; - Назначение (EKU) — TLS-клиент требует у сертификата сервера расширение
serverAuth, сервер у клиента —clientAuth. Если у сервера прописан толькоclientAuth, rustls оборвет соединение с ошибкой видаInvalidCertificate; - Имя хоста — клиент сверяет домен, к которому подключается (например,
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 |
| Дамп CSR | openssl req -in req.csr -text -noout |
| Проверка самоподписи CSR | openssl 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 со всеми именами подключения и убедиться, что пара «сертификат/ключ» совпадает по дайджестам.