HSTS (HTTP Strict Transport Security) — указание браузеру: «к этому домену ходи только по HTTPS, без исключений».
Strict-Transport-Security: max-age=31536000; includeSubDomains
Получив такой заголовок, браузер запоминает домен на указанный срок и подставляет https:// сам, ещё до отправки запроса. Даже если человек наберёт адрес без протокола или перейдёт по старой http://-ссылке.
Зачем это, если редирект уже стоит
Редирект работает, но с задержкой: первый запрос всё-таки уходит по HTTP. В этот момент его можно перехватить и подменить ответ, отправив человека на поддельный сайт (атака sslstrip). Окно небольшое, но оно есть — особенно в открытых Wi-Fi-сетях.
HSTS закрывает это окно: незащищённый запрос не отправляется вообще. Плюс сокращается цепочка редиректов — браузер сразу идёт по правильному адресу.
Параметры
- max-age — сколько секунд помнить. Год (31536000) — стандартное значение. Начинать стоит с малого:
max-age=300. - includeSubDomains — правило распространяется на все поддомены. Мощно и опасно: любой поддомен, который ещё живёт по HTTP, станет недоступен.
- preload — заявка на включение домена в списки, встроенные в браузеры. Тогда HTTPS будет обязательным даже при самом первом визите.
Чем это опасно
Отменить нельзя. Пока не истечёт max-age, браузер посетителя будет ходить только по HTTPS. Если сертификат просрочится или сломается, человек увидит ошибку без кнопки «всё равно перейти» — и сайт будет недоступен, пока вы не почините сертификат. Сбросить это удалённо невозможно.
Preload-список — почти навсегда. Удаление из встроенных списков занимает месяцы и приходит к людям только с обновлением браузера.
Как включать правильно
- Убедитесь, что весь сайт и все поддомены работают по HTTPS, а смешанного контента нет.
- Настройте автопродление сертификата и проверьте, что оно работает.
- Начните с короткого срока:
add_header Strict-Transport-Security "max-age=300" always;
- Через неделю без проблем поднимите до месяца, потом до года.
includeSubDomains— только когда проверены все поддомены, включая почтовые и технические.preload— в последнюю очередь и осознанно.
Директива always в nginx обязательна: без неё заголовок не добавляется к ответам с ошибками.
Apache:
Header always set Strict-Transport-Security "max-age=31536000"
Как проверить
- Пункт аудита «HSTS».
- Из консоли:
curl -I https://example.ru/ | grep -i strict-transport
- В браузере Chrome служебная страница
chrome://net-internals/#hstsпозволяет посмотреть и сбросить состояние для конкретного домена — полезно при отладке на своей машине.