Как работает HTTPS и TLS: практическое руководство
Вы видели значок замка в браузере и знаете, что HTTPS важен. Но действительно ли вы понимаете, что происходит, когда браузер подключается к HTTPS-сайту? Многие разработчики воспринимают TLS как чёрный ящик — настраивают один раз и забывают. Это работает, пока что-то не сломается, не пострадает производительность или аудит безопасности не выявит ошибки конфигурации.
Это руководство объясняет HTTPS и TLS на практике. Вы узнаете о процессе рукопожатия, о том, как сертификаты устанавливают доверие, и о шагах для правильной реализации TLS на ваших серверах. Без перегруза жаргоном — только концепции, нужные для отладки проблем и принятия обоснованных решений.
Что такое HTTPS на самом деле
HTTPS — это HTTP поверх TLS (Transport Layer Security). Он обеспечивает три гарантии:
- Шифрование: Данные, передаваемые между клиентом и сервером, нечитаемы для посторонних.
- Аутентификация: Клиент проверяет, что общается с легитимным сервером, а не с самозванцем.
- Целостность: Данные не могут быть изменены при передаче незаметно.
TLS — это протокол, который делает это возможным. SSL — его предшественник; вы всё ещё увидите «SSL-сертификаты» в маркетинге, но современные системы используют TLS (сейчас актуальна версия TLS 1.3).
TLS-рукопожатие: шаг за шагом
Прежде чем пойдут какие-либо HTTP-данные, клиент и сервер выполняют рукопожатие, чтобы согласовать параметры шифрования и проверить идентичность. Вот упрощённый поток для TLS 1.3, современного стандарта:
- Client Hello: Браузер отправляет список поддерживаемых шифровых наборов, версий TLS и случайное значение (client random).
- Server Hello: Сервер выбирает шифровой набор, отправляет своё случайное значение (server random) и предоставляет цепочку сертификатов.
- Обмен ключами: Используя эфемерный Diffie-Hellman (или аналогичный), обе стороны выводят общий секрет, не передавая его напрямую. Это обеспечивает прямую секретность (forward secrecy) — компрометация закрытого ключа сервера в будущем не расшифрует прошлые сессии.
- Проверка сертификата: Клиент проверяет сертификат по доверенным корневым CA, проверяет доменное имя, срок действия и статус отзыва.
- Finished: Обе стороны отправляют MAC (код аутентификации сообщения), подтверждая, что рукопожатие не было изменено. Начинается зашифрованный HTTP-трафик.
TLS 1.3 сократил рукопожатие до одного кругового обмена (1-RTT) и поддерживает возобновление 0-RTT для повторных посетителей, улучшая задержку. TLS 1.2 требовал двух круговых обменов.
Сертификаты: якорь доверия
TLS-сертификат связывает открытый ключ с доменным именем и подписан удостоверяющим центром (CA). Когда ваш браузер подключается к example.com, он проверяет, что сертификат:
- Подписан CA из его хранилища доверия (или выстраивается в цепочку к нему).
- Соответствует доменному имени (через Subject Alternative Names).
- Находится в пределах срока действия.
- Не был отозван (через OCSP или CRL, хотя применение различается).
Вы можете бесплатно получить сертификаты от Let's Encrypt, который выдаёт 90-дневные сертификаты через протокол ACME. Инструменты автоматизации, такие как Certbot, выполняют продление. Для внутренних сервисов можно запустить собственный CA, но клиенты должны явно ему доверять.
Настройка TLS на вашем сервере
Правильная конфигурация балансирует безопасность, совместимость и производительность. Вот чек-лист:
- Используйте только TLS 1.2 и 1.3. Отключите TLS 1.0 и 1.1 — они устарели и уязвимы.
- Выбирайте стойкие шифровые наборы. Предпочитайте AEAD-шифры, такие как AES-GCM или ChaCha20-Poly1305. Избегайте режима CBC и RC4.
- Включите прямую секретность. Используйте обмен ключами ECDHE.
- Включите OCSP stapling. Сервер включает кэшированный ответ OCSP, снижая задержку на стороне клиента и утечки конфиденциальности.
- Настройте заголовки HSTS. Заставьте браузеры использовать HTTPS для будущих посещений.
- Перенаправляйте HTTP на HTTPS. Убедитесь, что открытый трафик не обслуживается.
Для 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_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
add_header Strict-Transport-Security "max-age=63072000" always;
location / {
proxy_pass http://localhost:3000;
}
}
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
Проверяйте конфигурацию с помощью инструментов вроде SSL Test от SSL Labs или testssl.sh. Стремитесь к оценке A, но не гонитесь за идеальными баллами ценой поломки старых клиентов, если вам нужно их поддерживать.
Частые ошибки и как их избежать
- Просроченные сертификаты: Автоматизируйте продление и следите за сроком действия. Один просроченный сертификат может уронить ваш сайт.
- Смешанный контент: Загрузка HTTP-ресурсов на HTTPS-странице вызывает предупреждения и ломает функциональность. Используйте относительные URL или HTTPS везде.
- Слабые протоколы: TLS 1.0/1.1 устарели. Обновите конфигурацию.
- Отсутствующие промежуточные сертификаты: Сервер должен отправлять полную цепочку (кроме корневого). Отсутствие промежуточных вызывает ошибки доверия у некоторых клиентов.
- Неправильные перенаправления: Перенаправляйте HTTP на HTTPS до обслуживания любого контента и используйте 301 для постоянных перенаправлений.
FAQ
В чём разница между HTTPS и TLS?
HTTPS — это HTTP поверх TLS. TLS — криптографический протокол, обеспечивающий шифрование, аутентификацию и целостность. HTTPS невозможен без TLS.
Нужен ли отдельный сертификат для www и без www?
Вы можете включить оба в поле Subject Alternative Names (SAN) одного сертификата. Большинство CA выдают сертификаты, покрывающие оба варианта, по умолчанию или при простой настройке.
Как часто нужно менять TLS-сертификаты?
Следуйте сроку действия CA — 90 дней для Let's Encrypt. Автоматизируйте продление с помощью cron-задачи или таймера systemd. Меняйте немедленно, если закрытый ключ скомпрометирован.
Готовы проанализировать свой веб-трафик? Используйте Анализатор логов Nginx, чтобы разобрать логи доступа и проверить HTTPS-запросы, коды состояния и потенциальные проблемы.