Любой администратор рано или поздно упирается в вопрос: как одна сторона может доверять открытому ключу другой стороны, не имея заранее общего секрета. Ответ - инфраструктура открытых ключей (PKI) на базе сертификатов X.509. В этом уроке разберём, из чего реально состоит сертификат, как строится цепочка доверия от листа до корня, как браузер и сервер проверяют отзыв (CRL, OCSP и то, что пришло им на смену в 2025-2026), и где живут доверенные хранилища в Debian и RHEL. Это фундамент для всего блока 331 (шифрование), поэтому копаем глубоко.

Как это работает
Сертификат X.509 - это структура данных в формате ASN.1, которая связывает открытый ключ с идентичностью (доменом, организацией, человеком) и скрепляется подписью удостоверяющего центра (CA). Подпись делается закрытым ключом CA по хешу тела сертификата (TBSCertificate). Проверяющий берёт открытый ключ CA, пересчитывает хеш тела и сверяет с расшифрованной подписью. Если совпало - тело не подменяли и его подписал именно владелец ключа CA.
Доверие не возникает из воздуха: оно делегируется по цепочке. Корневой CA (root) самоподписан, его открытый ключ заранее лежит в доверенном хранилище ОС или браузера. Корень подписывает промежуточные CA (intermediate), а те - листовые (leaf, end-entity) сертификаты серверов. Проверяющий идёт снизу вверх: лист подписан промежуточным, промежуточный - корнем, корень есть в хранилище - значит, цепочка валидна. Корневой ключ почти всегда держат офлайн, а на каждый день работают промежуточные - так компрометация рабочего ключа не убивает весь корень.
Версия X.509v3 добавила расширения (extensions) - именно они несут почти всю практическую логику. Ключевые поля и расширения: Subject и Issuer (кто владелец и кто подписал), Validity (notBefore/notAfter - срок жизни), Subject Public Key Info (сам ключ и алгоритм), Serial Number (уникален в рамках CA), Subject Alternative Name (SAN - список доменов и IP; CN для имени хоста уже легаси и игнорируется браузерами), Basic Constraints (CA:TRUE/FALSE - можно ли этим сертификатом подписывать другие), Key Usage и Extended Key Usage (для чего ключ - подпись, шифрование, serverAuth, clientAuth), Authority Key Identifier и Subject Key Identifier (склейка звеньев цепочки).
Отзыв решает задачу досрочного аннулирования: ключ утёк или сертификат выдан по ошибке. Классических механизма два. CRL (Certificate Revocation List) - подписанный CA список отозванных серийных номеров, ссылка на него лежит в расширении CRL Distribution Points. OCSP (Online Certificate Status Protocol) - онлайн-запрос по одному сертификату к responder из расширения Authority Information Access. У OCSP была проблема приватности (responder видит, какие сайты вы открываете) и soft-fail (недоступен - считаем валидным). Поэтому к 2026 индустрия ушла от классического OCSP: Let's Encrypt полностью выключил OCSP-сервис 6 августа 2025 и оставил только CRL, а браузеры перешли на собранные на своей стороне списки - CRLite в Firefox (с версии 142 в августе 2025 OCSP для DV отключён) и CRLSets в Chrome. Параллельно резко сокращается срок жизни: по решению CA/Browser Forum (ballot SC-081) максимум падает поэтапно - 200 дней с 15 марта 2026, 100 дней с 15 марта 2027 и 47 дней с 15 марта 2029. Короткий срок сам по себе снижает цену проблемы отзыва, но делает автоматизацию (ACME) обязательной.
Сверх этого работает Certificate Transparency (CT): каждый публичный сертификат CA обязан опубликовать в открытых append-only логах, браузеры требуют доказательства включения (SCT). Это позволяет владельцу домена заметить левый сертификат на своё имя.
Команды и примеры
Посмотреть содержимое сертификата (поля, расширения, цепочку):
Код: Выделить всё
openssl x509 -in server.crt -noout -text
openssl x509 -in server.crt -noout -subject -issuer -dates -serial
openssl x509 -in server.crt -noout -ext subjectAltName,basicConstraints,keyUsageКод: Выделить всё
openssl verify -CAfile chain.pem server.crt
openssl s_client -connect cyberlake.ru:443 -servername cyberlake.ru -showcerts < /dev/nullКод: Выделить всё
# положить корень и обновить хранилище
cp myroot.crt /usr/local/share/ca-certificates/myroot.crt
update-ca-certificates --fresh
# итоговый bundle:
ls -l /etc/ssl/certs/ca-certificates.crtКод: Выделить всё
cp myroot.crt /etc/pki/ca-trust/source/anchors/myroot.crt
update-ca-trust extract
trust list --filter=ca-anchors | headКод: Выделить всё
openssl crl -in revoked.crl -noout -text | head
# узнать URL CRL прямо из сертификата:
openssl x509 -in server.crt -noout -ext crlDistributionPointsКод: Выделить всё
openssl ocsp -issuer chain.pem -cert server.crt \
-url http://ocsp.example.org -no_nonce -text- Сервер отдаёт только листовой сертификат без промежуточных. У клиента с пустым кешем цепочка не достроится. Всегда отдавайте leaf + intermediate (fullchain), но НЕ корень - он и так в хранилище.
- Доверять CN вместо SAN. Современные браузеры читают только SAN, CN игнорируется. Нет нужного домена в SAN - ошибка имени.
- Перепутан порядок в bundle. В PEM-цепочке сначала листовой, затем промежуточные снизу вверх. Неверный порядок ломает часть клиентов.
- Расчёт на OCSP stapling с сертификатами Let's Encrypt после мая 2025 - в них нет OCSP URL, стейплить нечего. Уберите ssl_stapling из конфигов nginx, чтобы не сыпать warning.
- Положили корень в хранилище, но забыли update-ca-certificates / update-ca-trust extract - файл лежит, а bundle не пересобран, доверие не появилось.
- notBefore в будущем из-за расхождения часов: свежий сертификат считается ещё невалидным. Держите NTP/chrony синхронизированными.
- 1. Создайте свой корневой CA: сгенерируйте ключ и самоподписанный сертификат с basicConstraints CA:TRUE (openssl req -x509 -newkey ec ...).
- 2. Выпустите промежуточный CA, подписав его корнем, тоже с CA:TRUE и pathlen:0.
- 3. Выпустите листовой сертификат на тестовый домен с SAN, подписав его промежуточным.
- 4. Соберите fullchain (leaf + intermediate) и проверьте openssl verify -CAfile с одним лишь корнем.
- 5. Установите свой корень в системное хранилище (Debian через /usr/local/share/ca-certificates, RHEL через anchors) и обновите его штатной командой.
- 6. Поднимите openssl s_server с этим сертификатом и проверьте curl без -k - доверие должно сработать.
- 7. Сгенерируйте CRL, отзовите серийник листа, и убедитесь, что openssl verify -crl_check теперь ругается.
- Чем отличаются поля Subject и Issuer и как по ним и по расширениям AKI/SKI проверяющий собирает цепочку?
- Зачем нужно расширение Basic Constraints и почему листовой сертификат с CA:TRUE - это дыра в безопасности?
- В чём приватностные и архитектурные минусы классического OCSP и чем его заменили браузеры к 2026 году?
- Почему достаточно отдавать клиенту leaf + intermediate и вредно вкладывать в цепочку корневой сертификат?
- Как сокращение срока жизни сертификатов (200/100/47 дней) связано с проблемой отзыва и с необходимостью ACME-автоматизации?
- Что такое Certificate Transparency и какую атаку с подложным сертификатом он помогает обнаружить?