HSTS (HTTP Strict Transport Security) — заголовок, который инструктирует браузер всегда использовать HTTPS для вашего домена, даже если пользователь набрал http://. Это защита от SSL-stripping атак и случайного перехода по HTTP.
Как работает HSTS
- Браузер впервые посещает сайт по HTTPS
- Получает заголовок
Strict-Transport-Security - Сохраняет домен в список HSTS на время max-age
- При следующем визите — автоматически открывает HTTPS без редиректа с сервера
Настройка через .htaccess
<IfModule mod_headers.c>
# Базовый HSTS: 1 год
Header always set Strict-Transport-Security "max-age=31536000"
# С включением поддоменов
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# С preload (для включения в браузерный список)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</IfModule>
Настройка через Nginx
server {
listen 443 ssl;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
}
max-age=300 (5 минут) для тестирования. Переключитесь на 31536000 только после того, как убедитесь что HTTPS работает идеально на всех поддоменах.HSTS Preload
Директива preload позволяет добавить домен в встроенные списки браузеров. Это означает, что HTTPS будет форсироваться даже при первом посещении (до получения заголовка):
- Подать заявку: hstspreload.org
- Требования: max-age не менее 1 года, includeSubDomains, действующий HTTPS на поддоменах
Проверка HSTS
# curl
curl -I https://example.com | grep Strict
# Или Chrome DevTools:
# Network → ваш запрос → Response Headers → Strict-Transport-Security
Разбор типичных ошибок с HSTS
NET::ERR_CERT_AUTHORITY_INVALIDбез кнопки «Перейти всё равно» — на HSTS-домене браузер не даёт обойти ошибку сертификата, как на обычном сайте. Если сертификат просрочен или выпущен для другого домена, сайт становится полностью недоступен до починки сертификата, а не просто «небезопасным».net::ERR_SSL_PROTOCOL_ERRORна поддомене при включённомincludeSubDomains— если хотя бы у одного поддомена нет рабочего HTTPS, браузер всё равно принудительно обращается к нему по HTTPS и получает ошибку соединения вместо мягкого отката на HTTP.net::ERR_TOO_MANY_REDIRECTS— типичный результат, когда редирект на HTTPS настроен одновременно и на CDN или балансировщике, и на самом сервере: два редиректа зацикливаются друг на друге.- Заголовок
Strict-Transport-Security, отправленный по обычному HTTP-соединению, браузер обязан проигнорировать по спецификации — если конфиг отдаёт его и на http, и на https, защита самого первого захода всё равно не появляется без включения в preload-список. - Страница
chrome://net-internals/#hsts— встроенный инструмент Chrome для проверки и ручного удаления локальной HSTS-записи браузера по конкретному домену, без ожидания истеченияmax-age.
Значения max-age: что когда выставлять
| Значение max-age | Продолжительность | Когда использовать | Риск |
|---|---|---|---|
| 300 | 5 минут | Тестирование настройки на реальном трафике | Минимальный — откатывается почти мгновенно |
| 86400 | 1 сутки | Первый этап продакшена после успешного теста | Ошибку ещё можно исправить в течение суток |
| 2592000 | 30 суток | Стабильная работа HTTPS без нареканий | Нужно поддерживать сертификат весь этот период без сбоев |
| 31536000 | 1 год | Финальная стадия, обязательное условие для preload | Откат недоступен для посетителей с уже сохранённой записью до истечения срока |
Когда HSTS ещё рано включать
- Сайт периодически обслуживает часть трафика по HTTP для легаси-интеграций — старых платёжных шлюзов или IoT-устройств без поддержки TLS — HSTS с длинным
max-ageсделает такие интеграции недоступными сразу для всех браузерных клиентов. - Поддомены выдаются пользователям автоматически, например SaaS на wildcard-домене, и не все гарантированно получают сертификат сразу —
includeSubDomainsзаблокирует доступ к ещё не подготовленным поддоменам. - Домен используется для локальной разработки или тестового стенда с самоподписанным сертификатом — HSTS с длинным сроком превратит любые дальнейшие эксперименты с сертификатами в необходимость вручную чистить настройки каждого браузера.
- Есть шанс, что домен придётся временно вернуть на HTTP — при миграции или смене CDN без TLS-терминации — preload-список редактируется медленно, удаление из него занимает месяцы, а до этого ни один браузер не откроет сайт по HTTP вообще.
Проверка, что HSTS реально защищает
# Проверить заголовок и его значение
curl -sI https://example.com | grep -i strict-transport-security
# Убедиться, что HTTP-версия того же домена всё ещё редиректит на HTTPS
curl -sI http://example.com | grep -i location
# В Chrome: chrome://net-internals/#hsts → Query domain → ввести домен
Поле static_sts_domain в результате запроса означает, что домен зашит в preload-список браузера, а не просто хранится в локальном кеше после первого визита. Это разные состояния: запись из кеша исчезнет сама по истечении max-age, запись из preload-списка — нет.