Learning Platform
Глоссарий Troubleshooting
Урок 12.03 · 25 мин
Средний
TLSCertificatesPKILet's EncryptX.509

Сертификаты и PKI — кто кому доверяет в интернете

В прошлом уроке мы говорили, что TLS-сервер представляется через сертификат, подписанный известной CA. Это звучит просто, но за этим стоит целая инфраструктура — PKI (Public Key Infrastructure). В 2026 году в браузеры и операционные системы предустановлено 100-200 root CA. Их подписи — основа доверия всего интернета.

В этом уроке: что внутри X.509 сертификата, как устроена цепочка доверия, что такое Let’s Encrypt и ACME, как сертификаты получаются и отзываются. Эти знания нужны, когда вы развёртываете сервер, troubleshoot’те TLS-ошибки или настраиваете mTLS между сервисами.


X.509: формат сертификата

Сертификат — это документ, привязывающий публичный ключ к identity (доменному имени, организации). Подписан выпустившей CA. Формат — X.509 (стандарт ITU из 1988 года, последний раз обновлён 2008).

X.509 сертификат содержит:

Структура X.509 сертификата
VersionВерсия формата X.509. Сейчас все используют v3. v1 и v2 устарели
Serial NumberУникальный номер сертификата в рамках выпустившей CA. Используется для revocation
Signature AlgorithmАлгоритм подписи: sha256WithRSAEncryption, ecdsa-with-SHA256 и т.д. Указывает, как CA подписала сертификат
IssuerDN (distinguished name) CA, выпустившей сертификат: CN=Let's Encrypt R3, O=Let's Encrypt, C=US
ValiditynotBefore -- с какой даты валиден. notAfter -- до какой. Браузер проверяет: текущее время должно быть в этом интервале
SubjectDN субъекта (владельца сертификата). Для server cert: CN=example.com (но modern предпочитает SAN extension вместо CN)
Subject Public KeyПубличный ключ субъекта. Тип: RSA 2048/4096, EC P-256/P-384, Ed25519. Это то, что используется в TLS handshake
ExtensionsSubject Alternative Names (SAN) -- список доменов (DNS:example.com, DNS:*.example.com), Key Usage, Extended Key Usage (serverAuth), CRL Distribution Points, OCSP URI
SignatureЦифровая подпись CA над всеми предыдущими полями. Гарантирует, что CA одобрила выпуск этого сертификата

Subject Alternative Names (SAN) — самое важное extension. Раньше домены указывались в CN (Common Name) поле Subject, но это устарело. Современные сертификаты используют SAN — список DNS-имён, для которых сертификат валиден:

X509v3 Subject Alternative Name:
    DNS:example.com, DNS:www.example.com, DNS:api.example.com, DNS:*.example.com

*.example.com — wildcard, валидный для всех direct поддоменов (a.example.com, b.example.com), но НЕ для a.b.example.com.

В одном сертификате может быть до сотен SAN. Часто используется для группы доменов одной компании.


Цепочка доверия: root, intermediate, leaf

В TLS handshake сервер шлёт не один сертификат, а цепочку:

Chain of trust
Root CA certSelf-signed (issuer == subject). Public key известен браузеру -- его прислали с дистрибутивом. Private key охраняется в HSM (hardware security module). Длится 20+ лет
ПодписьRoot CA подписывает intermediate CA своим private key. Цепочка доверия: ктоверит root, верит intermediate
Intermediate CA certIssued by root, used for daily issuance. Если intermediate скомпрометирован -- его отзывают, root остаётся. Срок жизни 5-10 лет
ПодписьIntermediate подписывает leaf-сертификаты
Leaf / Server certСертификат, который сервер показывает клиентам. Содержит ключ сервера, доменные имена. Let's Encrypt -- срок 90 дней, commercial -- год

Зачем такая многослойность?

  1. Безопасность root. Root CA имеет максимально ценный private key — если его украдут, нужно перевыпускать всё. Поэтому он редко используется: подписывает только intermediates, лежит offline в HSM.
  2. Гибкость. Если intermediate скомпрометирован, отзывают его — root и другие intermediates продолжают работать. Damage contained.
  3. Браузеры доверяют только roots. Все root certs предустановлены в браузер/ОС. Чтобы выпустить intermediate, root его подписывает — браузер доверяет.

Когда клиент подключается:

  1. Сервер шлёт [leaf, intermediate] (root знает клиент сам).
  2. Клиент: «Подписан ли leaf intermediate’ом? — да». «Подписан ли intermediate root’ом, которому я доверяю? — да». «Все проверки прошли? (validity, domain match, …)» — если да, валидно.

Validation: что именно проверяет браузер

При получении сертификата клиент делает обширную валидацию:

  1. Подпись каждой ступени цепочки. Криптографически проверяется через public key выше.
  2. Цепочка заканчивается на доверенном root. Браузер сверяется со своим trust store (Mozilla NSS, Apple Security, Windows Cert Store).
  3. Срок действия. Текущее время должно быть в [notBefore, notAfter] для каждого сертификата в цепочке.
  4. Совпадение имени. SAN сертификата должен содержать домен, к которому подключились.
  5. Key Usage / Extended Key Usage. Сертификат должен иметь EKU=serverAuth для веб-серверов.
  6. Revocation status. Через OCSP или CRL проверяется, не был ли сертификат отозван.

Если хоть что-то не сошлось — ошибка.


Типы валидации: DV vs OV vs EV

Сертификаты различаются по уровню проверки владельца, прежде чем CA его выдала:

Типы сертификатов по уровню валидации
DV (Domain Validation)CA проверяет только control над доменом (через DNS, HTTP-вызов, email). Минимальная валидация. Бесплатно (Let's Encrypt), быстро (минуты). Это 95% серверных сертификатов
OV (Organization Validation)CA дополнительно проверяет, что организация существует (документы, регистрация). Сертификат содержит O=имя организации. Платно, выдача неделя
EV (Extended Validation)Максимально строгая проверка: документы, операционная история, личный контакт. Раньше браузер показывал зелёное имя компании в адресной строке. Сейчас UI убрали (Chrome 77+)

Раньше EV-сертификаты показывались красиво (зелёный замок с именем компании). Считалось, что это даёт пользователю доверие. Исследования показали, что пользователи не замечают — и Chrome/Firefox убрали UI. В 2026 году EV-сертификаты не дают визуального преимущества; их используют в основном по compliance-причинам.

Practically: 95% сертификатов на интернете — бесплатные DV от Let’s Encrypt. Для большинства задач этого достаточно.


Let’s Encrypt и ACME

До 2015 года получение TLS-сертификата стоило $50-500/год и требовало ручной процедуры: генерация CSR, заполнение форм, ожидание verification, скачивание cert, установка на сервер. Это убивало adoption HTTPS на средних/мелких сайтах.

В 2015 году консорциум (EFF, Mozilla, …) запустил Let’s Encrypt — бесплатную CA с автоматизированным выпуском. Ключевой компонент — протокол ACME (Automatic Certificate Management Environment, RFC 8555).

ACME работает так:

ACME workflow
1. AccountКлиент (например, certbot) создаёт account на Let's Encrypt. Генерируется account key
2. OrderКлиент просит сертификат для доменов example.com, www.example.com. CA отвечает challenges -- задачами для proof of control
3. ChallengeЧаще всего HTTP-01: положить файл http://example.com/.well-known/acme-challenge/TOKEN с указанным content. DNS-01: создать TXT-запись. TLS-ALPN-01: специальный TLS handshake
4. CA verifiesCA сам делает HTTP-запрос или DNS-резолв с разных географических точек, проверяет content/значение. Если ОК -- domain control подтверждён
5. CSRКлиент генерирует RSA или EC private key + CSR (Certificate Signing Request). Шлёт CSR в CA
6. CertificateCA подписывает CSR -- выпускает сертификат. Клиент скачивает leaf + intermediate. Срок -- 90 дней

ACME полностью автоматизирован. На вашем сервере certbot (или caddy, или acme.sh) запускается раз в день, проверяет: «срок сертификата близок к концу? — да, давай обновим». Тихо, без участия человека.

К 2026 году Let’s Encrypt выпустил больше 6 миллиардов сертификатов. Изменил интернет: HTTPS adoption с 30% (2015) до 95%+ (2026).

TIP

Современные production setup’ы используют cert-manager в Kubernetes или Caddy как reverse proxy — они автоматизируют ACME полностью. Сервер с TLS из коробки за пять минут.


Срок сертификата: 90 дней vs год

Let’s Encrypt выпускает сертификаты на 90 дней. Это намеренно мало — заставляет автоматизировать renewal. Почему короткий срок лучше:

  1. Лимитирование damage. Если private key скомпрометирован, окно для злоупотреблений короче.
  2. Forced automation. 90 дней нельзя renew руками — обязательно скриптовать. Автоматизация работает надёжнее.
  3. Faster propagation of changes. Если revocation в реальности не работает (см. ниже), 90-дневный срок естественно лимитирует.

Commercial CA (DigiCert, Sectigo) выпускают на год. Но индустрия движется к короче — браузеры уже не принимают сертификаты с notAfter > 397 дней (CA/Browser Forum policy).

В 2025-2026 году обсуждается 45-дневный лимит — ещё короче. Это требует от всех более robust автоматизации.


Revocation: как отозвать сертификат

Допустим, private key утёк. Что делать? Отозвать сертификат — сообщить миру, что доверия ему больше нет. Способы:

  1. CRL (Certificate Revocation List). CA публикует список отозванных серийных номеров. Клиент скачивает CRL, проверяет, есть ли там cert сервера. Минусы: CRL большие (десятки МБ), клиент не часто обновляет.

  2. OCSP (Online Certificate Status Protocol). Клиент при подключении к серверу спрашивает CA: «cert с серийником X отозван?». CA отвечает «valid» или «revoked». Минусы: дополнительный roundtrip, privacy (CA знает, какие сайты вы посещаете).

  3. OCSP stapling. Сервер сам периодически спрашивает CA, кэширует ответ и прикладывает его к TLS handshake. Клиент видит «вот свежий OCSP-ответ от CA — cert valid». Решает обе проблемы. Стандарт в современных серверах.

Большая проблема: в реальности браузеры soft-fail OCSP. Если ответа нет (CA down, network issue) — они допускают подключение. Это значит, что revocation в большинстве случаев не работает — атакующий просто блокирует OCSP-запрос, и браузер принимает украденный cert.

Поэтому индустрия движется к short-lived certs (90 дней) как primary revocation mechanism: если cert украден — он сам истечёт через короткое время.

Browsers и CRLite (Mozilla), CRLSets (Chrome) — агрегированные списки отозванных certs, доставляемые с обновлениями браузера. Работают лучше, чем live OCSP.


Wildcard и multi-SAN сертификаты

Один сертификат может покрывать несколько доменов:

SAN: DNS:example.com
     DNS:www.example.com
     DNS:*.example.com    <- wildcard для всех direct поддоменов
     DNS:api.example.com  <- explicit (даже если есть *)
     DNS:*.api.example.com <- wildcard для второго уровня

Wildcard ограничения:

  • *.example.com валиден для a.example.com, b.example.com, но НЕ a.b.example.com (нужен *.b.example.com).
  • Не может быть в TLD: *.com — запрещено.
  • Single asterisk, всегда в самом начале: *.example.com — да, a.*.com — нет.

Multi-SAN сертификат может содержать до сотен явных имён. Часто используется для группы сайтов одной компании.


Mutual TLS (mTLS) — клиент тоже подтверждает identity

В обычном TLS клиент проверяет сервер (через cert + CA), но сервер обычно НЕ проверяет клиента — только пускает любого (аутентификация делается на application level через токены).

В mTLS клиент тоже шлёт свой сертификат, сервер валидирует. Это даёт cryptographic identity клиента вместо bearer tokens. Применения:

  • Service-to-service в microservices. Каждый сервис имеет свой client cert, выданный internal CA.
  • API между организациями. Banking, healthcare — регуляторы требуют mTLS для inter-organization API.
  • VPN-альтернатива. OpenVPN, WireGuard используют публичные ключи (по сути — упрощённый mTLS).

В Kubernetes + Service Mesh (Istio, Linkerd) — mTLS автоматический. Каждый pod имеет свой cert, обновляется автоматически. Это де-факто стандарт для security в k8s.


Реальный пример: получить cert через certbot

# Установка (Ubuntu/Debian)
sudo apt install certbot python3-certbot-nginx

# Получить сертификат для домена + автоматически настроить nginx
sudo certbot --nginx -d example.com -d www.example.com

# Что происходит под капотом:
# 1. Certbot генерирует new account key (если нет)
# 2. Регистрируется в Let's Encrypt
# 3. Делает order для example.com, www.example.com
# 4. Получает HTTP-01 challenge (token + path)
# 5. Modifies nginx config -- временно serves /.well-known/acme-challenge/TOKEN
# 6. Let's Encrypt с своих серверов делает HTTP-запрос на ваш сервер -- проверяет
# 7. Если ОК -- генерирует CSR с private key
# 8. Получает signed cert от LE
# 9. Сохраняет в /etc/letsencrypt/live/example.com/
# 10. Обновляет nginx config с путями к cert -- перезагружает nginx

# Автоматическое renewal -- через systemd timer или cron
sudo certbot renew --dry-run

# Через 60 дней (срок сертификата 90 дней, renew за 30) автоматический renew

Попробуй сам

# 1. Посмотреть на сертификат любого сайта
openssl s_client -connect github.com:443 -servername github.com < /dev/null 2>/dev/null | openssl x509 -text | head -40

# Что увидите:
# Issuer: CN=DigiCert TLS RSA SHA256 2020 CA1
# Subject: CN=github.com
# Validity: Not Before, Not After
# Subject Public Key Info: RSA 2048 bit
# X509v3 Subject Alternative Name: DNS:github.com, DNS:*.github.com

# 2. Получить только список SAN
openssl s_client -connect github.com:443 -servername github.com < /dev/null 2>/dev/null | openssl x509 -text | grep -A 5 'Subject Alternative Name'

# 3. Посмотреть полную цепочку
openssl s_client -connect github.com:443 -showcerts < /dev/null 2>/dev/null | grep -E 'subject|issuer|---'

# 4. Сертификат для одного домена через crt.sh (Certificate Transparency)
# https://crt.sh/?q=example.com  -- показывает все сертификаты, выпущенные на example.com
# Это полезно для security audit: 'кто выпускал cert на наш домен?'

# 5. Создать самоподписанный сертификат для тестирования
openssl req -x509 -newkey rsa:2048 -nodes \
  -keyout /tmp/key.pem -out /tmp/cert.pem -days 365 \
  -subj '/CN=localhost' -addext 'subjectAltName=DNS:localhost,DNS:test.local'

# Посмотреть, что получилось
openssl x509 -in /tmp/cert.pem -text | head -30

# 6. Использовать самоподписанный cert в Python HTTPS-сервере (только для тестов)
python3 -c "
import http.server, ssl
server = http.server.HTTPServer(('localhost', 8443), http.server.SimpleHTTPRequestHandler)
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain('/tmp/cert.pem', '/tmp/key.pem')
server.socket = ctx.wrap_socket(server.socket, server_side=True)
print('Listening on https://localhost:8443')
server.serve_forever()
"

# В другом терминале:
# curl --insecure https://localhost:8443  -- работает (--insecure пропускает проверку)
# curl https://localhost:8443  -- ошибка: cert не доверенный

Что вы должны вынести

  1. X.509 сертификат содержит public key + identity + signature CA.
  2. Доверие через chain: leaf -> intermediate -> root, root предустановлен в браузер.
  3. Subject Alternative Names (SAN) — современный способ указания доменов.
  4. DV / OV / EV различаются по уровню валидации. DV (Let’s Encrypt) бесплатные и быстрые.
  5. ACME полностью автоматизирует выпуск + renewal. certbot, caddy, cert-manager.
  6. Срок сертификата короткий (90 дней) — forced automation, лимит damage.
  7. Revocation (CRL, OCSP) в реальности не работает надёжно — short-lived certs основной механизм.
  8. mTLS добавляет client cert — стандарт для internal services через service mesh.

cert-manager и mTLS в Kubernetes: автоматизация PKI на уровне кластера Certificate pinning и HSTS для production API
Проверка знанийKnowledge check
У вас в production упал сайт. Браузер показывает 'NET::ERR_CERT_AUTHORITY_INVALID'. Что это значит, как diagnosticate и какие три самых вероятных причины?
ОтветAnswer
NET::ERR_CERT_AUTHORITY_INVALID -- браузер не доверяет цепочке сертификатов: либо корневая CA не в trust store, либо intermediate cert отсутствует. Diagnostic: первое -- запустить openssl s_client -connect domain:443 -servername domain и посмотреть Verify return code. Если 'self signed certificate' (18) или 'unable to get local issuer certificate' (20) -- это chain проблема. Три вероятных причины и решения: (1) Missing intermediate certificate в server config. Самая частая причина. Сервер отдаёт только leaf cert, не отдавая intermediate. Браузер не может построить цепочку до доверенного root. В firefox/chrome нормально работает (они кэшируют intermediates), но в curl/openssl без кэша -- ошибка. Lighthouse, обнаружение через openssl s_client (видим только один cert в chain). Решение: сложить fullchain.pem (leaf + intermediate) в nginx ssl_certificate. Let's Encrypt fullchain.pem уже содержит оба, надо просто указать правильный путь. (2) Self-signed certificate в production. Кто-то выкатил setup с самоподписанным cert (например, dev configuration попало в prod). Diagnostic: openssl x509 -in cert.pem -text -- Issuer == Subject (own DN), это self-signed. Решение: выпустить нормальный cert через Let's Encrypt + ACME (5 минут с certbot). (3) Expired intermediate. Реже, но было известное событие в 2020 году -- Let's Encrypt's old intermediate IdenTrust DST Root CA X3 истёк, и серверы, у которых был старый intermediate в chain, начали падать. Diagnostic: openssl s_client -- видим Verify return code 'certificate has expired'. Решение: обновить cert через certbot (новый intermediate в новых certs). Бонус-проверка через https://www.ssllabs.com/ssltest/ -- даёт детальный отчёт, в том числе chain issues.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 6. Сервер представляется сертификатом, выпущенным Let's Encrypt. Когда клиент валидирует цепочку, что именно проверяется кроме срока действия?

Закончили урок?

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

Войдите чтобы оценить урок

Прогресс модуля
0 из 4