Глава 3

HTTPS и TLS

Разберём почему HTTP небезопасен, как TLS решает три ключевые проблемы и как устроены сертификаты и цепочки доверия.

📖 ~20 мин Основы

Зачем нужен TLS

HTTP — это чистый текст. Всё что передаётся между браузером и сервером можно перехватить и прочитать. Логин, пароль, токен, личные данные — всё в открытом виде.

✉️
Аналогия: прозрачный конверт Представь что ты отправляешь письмо в прозрачном конверте через множество посредников — каждый почтальон может его прочитать и подменить содержимое. HTTP работает именно так.

Посмотри что происходит с данными в пути при HTTP и HTTPS:

⚠ HTTP — данные открыты
🌐
Браузер
POST /login → "password": "qwerty"
↓ открытый текст
📡
Роутер WiFi
👁 видит: "password": "qwerty"
↓ открытый текст
🔌
Провайдер
👁 видит: "password": "qwerty"
↓ открытый текст
🖥️
Сервер
получил: "password": "qwerty"
👁 Любой в пути может читать данные
✓ HTTPS — данные зашифрованы
🌐
Браузер
POST /login → шифрует данные
↓ зашифровано
📡
Роутер WiFi
↓ зашифровано
🔌
Провайдер
↓ зашифровано
🖥️
Сервер
расшифровал: "password": "qwerty"
🔐 Только сервер может прочитать данные

TLS (Transport Layer Security) — протокол который решает три проблемы одновременно:

HTTPS = HTTP + TLS. Никакого нового протокола — тот же HTTP, просто завёрнутый в TLS-туннель.

ℹ️
SSL vs TLS SSL (Secure Sockets Layer) — предшественник TLS. Эволюция: SSL 3.0 → TLS 1.0 → TLS 1.1 → TLS 1.2 → TLS 1.3. SSL давно устарел и небезопасен, но слово «SSL» прижилось в обиходе. Когда говорят «SSL-сертификат» — имеют в виду TLS-сертификат.

Что такое сертификат

Сертификат — это цифровой документ. Когда браузер подключается к сайту, сервер отдаёт сертификат — и браузер проверяет что перед ним именно тот сервер, а не кто-то, кто прикидывается им.

📜
TLS Certificate
X.509 v3 — цифровой сертификат
✓ Действителен
Для кого выдан CN: example.com
Список доменов (SAN) example.com, www.example.com, api.example.com
Кем выдан Let's Encrypt Authority X3
Действителен с 2024-01-15 00:00:00 UTC
Действителен до 2025-01-15 23:59:59 UTC
Публичный ключ RSA 2048 bit
Подпись CA SHA256withRSA — ✓ валидна

Файл .crt — это часто не один сертификат

Файл сертификата нередко содержит цепочку — твой сертификат плюс Intermediate CA. Это называется bundle или fullchain. nginx должен отдавать браузеру полную цепочку — иначе браузер не сможет построить путь доверия до Root CA.

PEM file
-----BEGIN CERTIFICATE-----
(твой сертификат example.com)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Intermediate CA)
-----END CERTIFICATE-----

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

Один сертификат сам по себе ничего не доказывает. Нужен кто-то кому доверяют все — это Root CA (корневой удостоверяющий центр).

Структура цепочки доверия
🏛️
Root CA
DigiCert Global Root CA
Самый верхний уровень. Его сертификат встроен в браузер и ОС при установке.
Вшит в систему
🔗
Intermediate CA
DigiCert TLS RSA SHA256 2020 CA1
Промежуточный центр. Root CA не выдаёт сертификаты сайтам напрямую — он подписывает Intermediate CA, а тот уже выдаёт сертификаты. Если Intermediate CA скомпрометирован — его отзывают, Root CA остаётся нетронутым.
Подписан Root CA
🌐
Твой сертификат
example.com
Выдан Intermediate CA для конкретного домена. Браузер получает его первым и строит цепочку наверх до Root CA.
Подписан Intermediate CA

Когда браузер получает твой сертификат — он строит цепочку и проверяет каждую подпись:

1
Твой сертификат подписан Intermediate CA? → проверяем подпись
2
Intermediate CA подписан Root CA? → проверяем подпись
3
Root CA есть в системном хранилище?
✓ Дабраузер показывает замочек
✗ Нет — «Ваше соединение не защищено»
⚠️
Внутренний корпоративный CA Если в организации есть свой Root CA — его сертификат не встроен в браузеры и ОС по умолчанию. Его нужно устанавливать вручную на каждое устройство через групповые политики (GPO), MDM или вручную. Именно поэтому внутренние сертификаты работают внутри компании, но на личном телефоне без установленного корневого сертификата браузер будет ругаться.

Что такое RTT

Прежде чем разбирать handshake, нужно понять один термин — он объясняет почему TLS 1.3 быстрее TLS 1.2.

RTT (Round-Trip Time) — время за которое пакет уходит от отправителя к получателю и возвращается обратно. Буквально: отправил → дошло → вернулось. Весь этот круг — один RTT.

Round-Trip Time — один круговой обмен
🌐
Клиент
Запрос
⟵ 1 RTT ⟶
Ответ
🖥️
Сервер
Москва–Москва: ~5–15 ms
Москва–Нью-Йорк: ~150 ms
Мобильная сеть: ~100–300 ms

RTT определяется физикой сети — расстоянием и скоростью света в кабеле. Его не ускорить никакими настройками. Каждый «круговой обмен» в handshake стоит ровно столько.

🏔️
Аналогия: эхо в горах Ты кричишь в горах и ждёшь эхо. Время от крика до того момента как услышал эхо — это RTT. Половина — путь туда, половина — обратно.
Bash
ping google.com
# 64 bytes from google.com: time=12.4 ms  ← это и есть RTT

Как работает TLS Handshake

Handshake — это переговоры между клиентом и сервером перед началом передачи данных. Они договариваются как будут шифровать соединение.

TLS 1.3
1 RTT — быстро
🌐
Клиент
🖥️
Сервер
ClientHello
версии TLS, алгоритмы,
публ. ключ DH, SNI
1й RTT начало
ServerHello
алгоритм, публ. ключ DH,
сертификат, Finished
канал зашифрован
Finished + HTTPS запрос
первый запрос идёт сразу
При RTT=100ms: 100ms — и данные идут
TLS 1.2
2 RTT — медленнее
🌐
Клиент
🖥️
Сервер
ClientHello
версии TLS, алгоритмы
1й RTT
ServerHello + сертификат
выбранный алгоритм
ClientKeyExchange + Finished
ключ обмена
2й RTT
ChangeCipherSpec + Finished
канал готов
HTTPS запрос
только теперь
🐢 При RTT=100ms: 200ms до первого байта

На мобильных сетях RTT легко достигает 200–300ms. Там разница между TLS 1.2 и TLS 1.3 становится очень ощутимой: 400–600ms против 200–300ms только на handshake.

SNI — как сервер выбирает нужный сертификат

SNI (Server Name Indication) — расширение ClientHello. Клиент сразу в первом сообщении указывает к какому домену обращается. Сервер смотрит на SNI и выбирает нужный сертификат ещё до того как отправит ServerHello.

Без SNI на одном IP можно держать только один сертификат. С SNI — сколько угодно доменов на одном IP, каждый со своим сертификатом. Именно поэтому хостинг-провайдеры могут держать тысячи сайтов с HTTPS на одном сервере.

💡
nginx и SNI В nginx каждый блок server {} с директивой ssl_certificate автоматически использует SNI — nginx сам выбирает нужный сертификат по server_name.

Асимметричное и симметричное шифрование

В TLS используются оба типа — каждый для своей задачи.

🔑🔑
Асимметричное
RSA, ECDSA, ECDHE
🔓
Публичный ключ
+
🔒
Приватный ключ
Два ключа: публичный и приватный. Работает в обе стороны:

🔓 публичным → расшифровывает приватный (шифрование данных)
🔒 приватным → расшифровывает публичный (цифровая подпись)

В TLS используется второй вариант — CA подписывает сертификат приватным ключом, браузер проверяет подпись публичным ключом CA. Медленное — только handshake
🔑
Симметричное
AES-256-GCM
🤝
Один общий ключ у обеих сторон
Один ключ, который обе стороны вычислили в ходе handshake. Используется для шифрования всех данных после handshake. Быстрое

Схема совместной работы:

1
Handshake (асимметричное — ECDHE)
Клиент и сервер обмениваются публичными параметрами и независимо вычисляют общий сессионный ключ. Сам ключ по сети не передаётся.
2
Передача данных (симметричное — AES)
Все данные шифруются быстрым AES с общим сессионным ключом. Ключ уникален для каждого соединения.

Forward Secrecy — совершенная прямая секретность

Современный TLS использует Diffie-Hellman обмен (ECDHE): обе стороны обмениваются публичными параметрами и независимо вычисляют общий сессионный ключ — он никогда не передаётся по сети.

Это называется Forward Secrecy: даже если приватный ключ утечёт, расшифровать записанный ранее трафик невозможно — сессионные ключи нигде не хранятся и заново не вычисляются.

⚠️
Приватный ключ всё равно нужно охранять С украденным приватным ключом злоумышленник может выдать себя за твой сервер и провести атаку «человек посередине» на новые соединения.