Как на самом деле работают HTTPS и TLS: разбор рукопожатия
Вы набрали https:// перед URL, увидели замок и пошли дальше. Но когда сертификат истекает в 2 часа ночи, предупреждение о смешанном содержимом ломает страницу оформления заказа, или клиент спрашивает, почему его API-запрос завершается ошибкой TLS, ответ «замок означает, что всё безопасно» перестаёт быть полезным. Эта статья объясняет, что на самом деле происходит на линии во время HTTPS-соединения и как настроить его без догадок.
Что HTTPS добавляет к HTTP
HTTPS — это обычный HTTP, передаваемый внутри сессии TLS (Transport Layer Security). TLS обеспечивает три конкретные гарантии:
- Конфиденциальность — трафик зашифрован, поэтому посредники не могут его прочитать.
- Целостность — вмешательство в передачу обнаруживается, и соединение прерывается.
- Аутентификация — сервер доказывает, что владеет закрытым ключом для предъявленного сертификата.
Обратите внимание, чего в этом списке нет: HTTPS ничего не говорит о том, заслуживает ли сервер доверия, есть ли у приложения уязвимости или безопасны ли данные при хранении. Он защищает канал, а не конечные точки.
TLS-рукопожатие шаг за шагом
Рукопожатие — это согласование, которое происходит до передачи любых байтов HTTP. В TLS 1.3 оно занимает один круговой обход; в TLS 1.2 нужно два. Вот поток TLS 1.3 простыми словами:
- ClientHello — клиент отправляет поддерживаемые версии TLS, список шифров, случайный nonce и долю ключа для обмена ключами Диффи-Хеллмана (обычно X25519).
- ServerHello — сервер выбирает версию и шифр, возвращает свою долю ключа и отправляет свою цепочку сертификатов плюс подпись над стенограммой рукопожатия.
- Выработка ключа — обе стороны вычисляют общий секрет из обмена Диффи-Хеллмана. Эфемерные ключи означают, что сессионный ключ уникален и обеспечивается прямая секретность: компрометация долгосрочного ключа сервера позже не позволит расшифровать записанный трафик.
- Finished — обе стороны отправляют MAC над стенограммой. Если что-то было изменено, рукопожатие прерывается.
- Данные приложения — HTTP-запросы и ответы шифруются симметричными ключами, производными от общего секрета.
Сертификат — это то, где живёт аутентификация. Сервер подписывает рукопожатие своим закрытым ключом; клиент проверяет эту подпись с помощью открытого ключа из сертификата, затем проверяет сам сертификат относительно доверенного корневого CA, проверяя имя хоста, сроки действия и статус отзыва.
Симметричное vs асимметричное: почему используются оба
Асимметричная криптография (RSA или ECDSA) медленная, но решает проблему распространения ключей. Симметричные шифры (AES-GCM, ChaCha20-Poly1305) быстрые, но требуют общего ключа. TLS использует асимметричную криптографию только во время рукопожатия для установления симметричного сессионного ключа, а затем шифрует этим ключом основные данные. Именно поэтому современное TLS 1.3-соединение быстрое: один круговой обход, а затем дешёвый AES или ChaCha20 для всего остального.
Шифры и что на самом деле важно
Шифр — это именованный набор алгоритмов. В TLS 1.3 список короткий, и все варианты считаются безопасными; в TLS 1.2 нужно выбирать осторожно. Краткое сравнение:
| Аспект | TLS 1.2 | TLS 1.3 |
|---|---|---|
| Круговых обходов рукопожатия | 2 (или 1 с возобновлением) | 1 (0-RTT с возобновлением) |
| Обмен ключами | RSA или (EC)DHE | Только эфемерный (EC)DHE |
| Прямая секретность | Опционально | Всегда |
| Устаревшие шифры (CBC, RC4) | Возможны при неверной настройке | Удалены |
Практический вывод: включайте только TLS 1.2 и 1.3, отключайте TLS 1.0/1.1 и предпочитайте сертификаты ECDSA для снижения затрат на рукопожатие. Позвольте серверу или обратному прокси выбирать порядок шифров; большинство настроек по умолчанию разумны в ПО 2024 года.
Как проверить реальное соединение
Не нужно верить документации — проверяйте свои конечные точки. openssl s_client показывает согласованную версию, шифр и цепочку сертификатов:
openssl s_client -connect example.com:443 -servername example.com -tls1_3 </dev/null
Посмотрите на строки Protocol и Cipher, затем проверьте вывод цепочки сертификатов на предмет срока действия и записей SAN. Если цепочка неполная, некоторые клиенты будут терпеть неудачу, в то время как браузеры будут работать — это классический источник ошибок «в Chrome работает, а в curl нет».
Распространённые ошибки настройки HTTPS
- Отсутствует промежуточный сертификат — сервер отправляет только свой конечный сертификат. Браузеры могут загрузить промежуточный, но API-клиенты часто этого не делают.
- Смешанное содержимое — HTTPS-страница загружает скрипт или изображение по HTTP; браузеры блокируют или понижают его. Проверьте с помощью консоли браузера.
- Нет HSTS — без
Strict-Transport-Securityпервый запрос по HTTP может быть перехвачен до того, как произойдёт перенаправление. - Слабые или устаревшие версии протокола — оставленный включённым TLS 1.0 для устаревшего клиента незаметно ослабляет каждое соединение.
- Истечение срока действия сертификата — автоматизируйте продление; ручное напоминание в календаре — не стратегия.
Разумная конфигурация сервера
Для Nginx минимальный современный блок выглядит так:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
Файл fullchain.pem — это то, что предотвращает проблему отсутствующего промежуточного сертификата. Держите перенаправление с порта 80 в отдельном блоке server, чтобы HTTP по-прежнему работал для задач ACME.
Что HTTPS не защищает
Как только запрос достигает вашего сервера, TLS завершён. Уязвимости инъекций, нарушенный контроль доступа, утечка секретов в логах и неправильно настроенный CORS — всё это находится выше транспортного уровня. Относитесь к TLS как к базовой линии, а не как к программе безопасности. Если вы отлаживаете инцидент, сразу отделяйте транспортные проблемы (сбои рукопожатия, просроченные сертификаты) от проблем приложения (500-е ошибки, плохие полезные нагрузки) — у них совершенно разные решения.
FAQ
Шифрует ли HTTPS путь URL и строку запроса?
Да. В HTTPS весь HTTP-запрос, включая путь и строку запроса, находится внутри зашифрованной записи TLS. Однако имя хоста (SNI) и IP-адрес назначения видны во время рукопожатия, если не используется Encrypted Client Hello.
Всегда ли TLS 1.3 быстрее TLS 1.2?
Обычно да, потому что он экономит один круговой обход и поддерживает возобновление 0-RTT. На соединениях с высокой задержкой разница заметна; в локальной сети она незначительна. Более крупный выигрыш в том, что TLS 1.3 полностью удаляет устаревшие шифры.
Нужен ли всё ещё HSTS, если я перенаправляю HTTP на HTTPS?
Да. Перенаправление помогает только после того, как браузер достиг вашего сервера. HSTS сообщает браузеру, что нужно полностью пропускать HTTP для будущих запросов, закрывая окно, в котором первый запрос мог быть перехвачен.
Когда вы проверяете развёртывание и вам нужно быстро проверить детали сертификата или декодировать захваченное рукопожатие, держите под рукой рабочий процесс на основе терминала — а если вы документируете результаты для команды, Markdown-редактор — быстрый способ превратить необработанный вывод openssl в читаемый отчёт.