SSL/TLS deep dive: cipher suites breakdown (key exchange, signature, bulk cipher, MAC), PKI cert chain (root/intermediate/leaf), Certificate Transparency, OCSP/CRL revocation, mTLS for service mesh. 3 scenarios: cert chain validation walkthrough, mTLS handshake (mutual cert verification), revocation check (OCSP query vs stapling). 2 ADRs: cipher suite selection (TLS 1.3 + AEAD + ECDHE), mTLS vs OAuth2 for service-to-service auth.
tls-handshake объясняет «как клиент договаривается о шифровании». На проде этого мало: появляются cipher suites, forward secrecy, mTLS, OCSP stapling, certificate transparency, ECH, session resumption, 0-RTT. SRE/security-инженеру, который конфигурирует Envoy/NGINX/Istio и читает openssl s_client без боли, нужен глубокий срез: что выбрать, что выключить, что мониторить.
Этот гайд про то, как TLS реально живёт в production: cert chain validation, mutual auth, revocation. Три сценария на диаграмме — три самых частых места, где TLS-конфигурация ломает прод.
TLS = согласовать общий секрет через асимметрию (DH) + подтвердить identity через PKI (cert signed by trusted CA) + дальше симметричное шифрование (AEAD). Все улучшения 1.0 → 1.3 — это сокращение RTT, удаление слабых криптопримитивов и обязательный forward secrecy.
Три уровня доверия:
Топология показывает все три уровня в одной картине:
Edges — это физические связи (запрос/ответ идут по одному edge, ответ — reverse animation): browser ↔ webserver, webserver → cert/key, intermediate → leaf/OCSP/CRL/CT, browser → trust store/OCSP/CRL, service-a → webserver для mTLS.
Браузер строит цепочку leaf → intermediate → root и проверяет каждое звено: SAN matches hostname, validity period, signature chain, корень в локальном trust store, SCT в leaf cert (доказательство публикации в CT log). Сервер шлёт leaf + intermediate, корень НЕ шлёт — он у клиента. Это самый частый источник NET::ERR_CERT_AUTHORITY_INVALID: забыли intermediate в chain, или intermediate сам expired. Правило: always serve full chain, не полагайтесь на AIA chasing.
Обе стороны предъявляют cert. Сервер шлёт CertificateRequest, клиент отвечает Certificate + CertificateVerify (подпись transcript'а своим private key — proof of ownership). Сервер валидирует через internal CA. Identity вшита в transport — без round-trip к auth-серверу, работает на L4. В service mesh (Istio/Linkerd) сертификаты ротируются автоматически каждые 24h через SPIFFE/SPIRE, приложение об этом не знает — сайдкар сам. Главный gotcha: cert rotation outage = весь intra-cluster traffic стоит. Алерт на cert expiry < 7d — must-have.
Cert украден → CA отзывает. Как клиент узнает? Naive OCSP (клиент → responder CA) добавляет +1 RTT, leak'ает посещения CA, ломается при downtime responder'а — поэтому большинство браузеров делают soft-fail (security theater). OCSP Stapling: сервер каждые несколько часов сам запрашивает OCSP response и прикрепляет к handshake (CertificateStatus extension). Клиент проверяет signature без отдельного запроса — нет RTT, нет privacy leak. Must-Staple делает stapled response обязательным (защита от downgrade). Операционная дыра: после revocation существующие клиенты с cached good response продолжают трастить leaf до TTL expiry (часы) — поэтому Firefox делает CRLite (bloom-filter всех revocations, push каждые 6h).
ADR-001: TLS 1.3 only, AEAD ciphers, ECDHE forward secrecy.
Контекст: TLS 1.0/1.1 deprecated с 2020 (PCI DSS требует 1.2+). TLS 1.2 имеет 300+ named cipher suites, большинство broken (RC4, 3DES, MD5, SHA-1, RSA key exchange без forward secrecy). Решение: TLS 1.3 only для Modern-профиля. Cipher list: TLS_AES_256_GCM_SHA384 (сервер с AES-NI), TLS_CHACHA20_POLY1305_SHA256 (mobile без AES-NI), TLS_AES_128_GCM_SHA256 (fallback). Key exchange: ECDHE x25519 (forward secrecy + быстрый). Auth: ECDSA P-256 (RSA-2048 fallback для legacy). Сертификаты от Let's Encrypt с auto-renewal каждые 60d. OCSP stapling enabled. Must-Staple не включён (false positives при кратковременных CA outages). Session ticket key ротируется каждые 24h — иначе компрометация ключа = расшифровка всех прошлых сессий, нарушение PFS. Цена: древние клиенты (Android < 5, IE < 11) обрезаются. Прайс ок для B2B/SaaS, не ок для consumer-сайтов в развивающихся странах — там TLS 1.2 с modern cipher list.
ADR-002: mTLS vs OAuth2 для service-to-service auth.
Контекст: два мейнстрим-подхода. mTLS = обе стороны предъявляют x509, identity = SAN/CN. OAuth2 client credentials = JWT bearer token, identity = sub claim. Решение: mTLS для intra-cluster (Istio/Linkerd auto-rotate через SPIFFE, identity вшита в transport, нет лишнего hop к auth server, L4-friendly). OAuth2 для cross-org / public APIs / mobile (мгновенная token revocation, гранулярные scopes, audit-friendly, нет cert distribution headache). Антипаттерн: OAuth для intra-cluster (бесполезный hop через auth server — latency + SPOF), mTLS для public APIs (cert distribution миллионам клиентов невозможна). Гибрид: mTLS на mesh edge + OAuth поверх для user identity (Istio JWT filter).
ADR-003: 0-RTT только для idempotent запросов.
TLS 1.3 PSK + 0-RTT позволяет клиенту слать данные в самом ClientHello — нулевая latency на resumption. Но: replay attack — атакующий перехватывает 0-RTT и шлёт ещё раз, сервер не отличит. Для POST /transfer 100$ это double-charge. Решение: 0-RTT включаем только для GET / OPTIONS / safe methods. Все state-changing — full handshake. Cloudflare и AWS CloudFront так и делают по умолчанию.
spiffe://cluster/ns/default/sa/service-a).*.example.com на everything — компрометация = RIP всех subdomains. Лучше SAN-cert или отдельные leaf'ы с ACME.Не выкатывайте mTLS на публичный API. Cert distribution и rotation для миллионов внешних клиентов невозможна операционно — OAuth2/API keys гораздо проще. mTLS — для intra-cluster и B2B-партнёров с контролируемым parc устройств.
Не включайте 0-RTT, если у вас нет дисциплины по idempotent методам. Цена за +0 RTT — риск double-charge. Если ваш framework не различает safe/unsafe методы на уровне роутинга — 0-RTT off.
Не делайте custom PKI, если есть Let's Encrypt. Free, automated, проверенный. Internal PKI оправдан только для mTLS внутри cluster (Vault/SPIRE), и то — берите готовое.
Не пинуйте сертификаты, если не контролируете rotation pipeline целиком. HPKP браузеры удалили именно за то, что один неверный pin = сайт мёртв на месяцы. Cert pinning остаётся только в mobile, и только с backup pin'ами и автоматическим механизмом push новой версии приложения.
Концепты:
Кейсы:
Книги и спецификации: