Что такое HSTS и как безопасно его включить
HSTS заставляет браузер обращаться к известному хосту только по HTTPS. Политика повышает защиту, но требует исправного TLS и осторожного увеличения срока.
HSTS (HTTP Strict Transport Security) — политика, которая предписывает браузеру обращаться к известному хосту только по HTTPS. Сайт передаёт её в заголовке ответа Strict-Transport-Security, а браузер запоминает на заданный срок. При следующей попытке открыть http://example.com браузер заменяет схему на https до отправки HTTP-запроса и не предлагает обойти ошибку сертификата.
HSTS дополняет обычный редирект с HTTP на HTTPS, но не заменяет его. Редирект срабатывает после незашифрованного обращения к серверу, поэтому первый запрос можно перехватить или изменить. Сохранённая HSTS-политика позволяет браузеру перейти на HTTPS локально. Она не исправляет уязвимости приложения, mixed content, просроченный сертификат или неправильную цепочку доверия.
Как работает Strict-Transport-Security
Минимальный заголовок выглядит так:
Strict-Transport-Security: max-age=300
max-age задаёт срок действия политики в секундах с момента получения ответа. Значение 300 означает пять минут. Каждый новый корректный HTTPS-ответ с этим заголовком обновляет срок, поэтому при постоянной отдаче политика остаётся активной. Отсутствие заголовка в одном из последующих ответов не отменяет уже сохранённое правило: оно действует до истечения срока.
Ключевое ограничение: браузер учитывает HSTS только в ответе, полученном по HTTPS без ошибок TLS. Такой же заголовок по HTTP игнорируется, иначе атакующий в открытой сети мог бы установить или сбросить чужую политику. Поэтому добавлять Strict-Transport-Security в ответ на порту 80 бессмысленно. Сначала сервер перенаправляет клиента на HTTPS, затем HTTPS-ответ сообщает HSTS.
Политика идентифицирует хост по доменному имени. Она не превращает недействительный сертификат в действительный и не применяется к IP-адресу как к HSTS-хосту. Если сертификат перестанет проходить проверку, пользователь известного HSTS-хоста обычно не сможет продолжить соединение через предупреждение. До включения длительного срока проверьте сертификат через проверку SSL и убедитесь, что его автоматическое продление действительно работает.
Что означают директивы
Полная распространённая форма содержит три элемента:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
`max-age`. Обязательная директива определяет, сколько секунд браузер считает хост HSTS-хостом. Большое значение усиливает постоянство политики, но увеличивает последствия ошибки. max-age=0, полученный по исправному HTTPS, просит браузер удалить политику этого хоста.
`includeSubDomains`. Необязательная директива распространяет правило на все уровни ниже: например, политика example.com затронет www.example.com, api.example.com и old.internal.example.com. Даже забытый поддомен с DNS-записью должен поддерживать HTTPS и иметь подходящий сертификат. Политики, которые поддомены установили самостоятельно, хранятся отдельно и не обязательно исчезнут при сбросе родительского хоста.
`preload`. Эта директива выражает намерение включить домен в браузерный preload-список, но сама по себе ничего не отправляет в список. Домен отдельно подают через официальный сервис. Его требования включают действительный сертификат, HTTP-редирект на HTTPS, HTTPS на всех поддоменах и заголовок на базовом домене с max-age не меньше года, includeSubDomains и preload. Требования могут меняться, поэтому перед подачей их проверяют заново.
Preload закрывает проблему самого первого посещения: браузер уже поставляется со знанием, что домен должен использовать HTTPS. Обратная сторона — запись встроена в версии браузеров. Удаление требуется запрашивать отдельно, распространение изменений занимает длительное время, а сроки в разных браузерах не гарантированы. Отключить preload одним max-age=0 невозможно. Официальный сервис прямо рекомендует не включать preload по умолчанию.
Почему раннее включение опасно
При коротком max-age ошибку можно переждать или исправить и отправить max-age=0. При годовом сроке часть посетителей продолжит принудительно использовать HTTPS, даже если администратор убрал заголовок. Возврат сайта на HTTP для них уже не будет рабочим аварийным планом.
Особенно рискован includeSubDomains. В зоне могут оставаться панели старого оборудования, тестовые хосты, сайты подрядчиков, почтовые веб-интерфейсы или имена, доступные только из корпоративной сети. Родительская политика применяется к ним независимо от того, участвовали ли их владельцы во внедрении. Недоступный HTTPS, неподходящее имя в сертификате или устаревший TLS сделают такой ресурс недоступным в браузере.
До HSTS необходимо устранить mixed content, настроить единый HTTPS-канонический адрес, проверить все точки завершения TLS — CDN, балансировщик и основной сервер — и отработать продление сертификатов. Заголовок должен присутствовать не только на странице 200 OK, но и на HTTPS-редиректах и ответах об ошибках. Это можно проверить через анализ заголовков безопасности и отдельно просмотреть фактические ответы в проверке HTTP-заголовков.
Безопасное поэтапное внедрение
Практический порядок снижает радиус возможной ошибки:
- Составьте список основного домена и всех поддоменов, включая вложенные, внутренние и временно неиспользуемые DNS-имена. Найдите владельца и назначение каждого ресурса.
- Настройте HTTPS, сертификаты и HTTP-редиректы. Проверьте страницы, API, загрузки, callback-адреса и ответы с кодами ошибок. Не включайте HSTS, пока критичный сервис зависит от HTTP.
- Запустите основной хост с
max-age=300безincludeSubDomains. Наблюдайте не меньше полного срока и проверьте поведение в нескольких браузерах. - Увеличьте срок, например до суток, затем до недели. После каждого изменения ждите полный срок текущей ступени, отслеживайте ошибки TLS и готовность отката.
- После отдельного аудита поддоменов добавьте
includeSubDomainsсначала с коротким сроком. Повторите ступени и только затем переходите к месяцу и более длительному периоду. - Рассматривайте годовой срок после стабильной эксплуатации. Решение о
preloadпринимайте отдельно: оно оправдано только при долгосрочной гарантии HTTPS для текущих и будущих поддоменов.
Ступени не являются формальностью. Браузеры пользователей хранят политику локально, поэтому сервер не может мгновенно отозвать уже выданный большой max-age. Полезно документировать дату каждой ступени, текущее значение, ответственного и проверенный способ аварийного выпуска сертификата.
Пример настройки HSTS в Nginx
Заголовок следует добавлять в серверный блок, который обслуживает TLS:
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
add_header Strict-Transport-Security "max-age=300" always;
root /var/www/example.com;
}
Параметр always заставляет Nginx добавлять поле независимо от кода ответа, в том числе к ошибкам, для которых обычное поведение add_header может отличаться. Это важно: посетитель может впервые получить не главную страницу, а 404 или 500, и политика должна быть последовательной.
В Nginx директивы add_header имеют правила наследования. Если внутри location объявлены собственные заголовки, набор с уровня server в некоторых конфигурациях перестаёт наследоваться. После изменения проверяйте несколько маршрутов и кодов ответа, а не только /. Также убедитесь, что CDN или другой reverse proxy не удаляет поле и не создаёт дубликаты с разными значениями.
Для порта 80 достаточно отдельного редиректа без HSTS:
server {
listen 80;
listen [::]:80;
server_name example.com;
return 308 https://example.com$request_uri;
}
Перед перезагрузкой выполните nginx -t, затем примените конфигурацию штатным способом. Проверьте HTTP-ответ, HTTPS-ответ, ошибочную страницу и каждый публичный hostname. Значение в примере специально короткое для первой ступени; механически заменять его на год и добавлять preload нельзя.
Типичные ошибки
- Отправлять HSTS только по HTTP. Браузер такой заголовок не запомнит.
- Сразу выставлять большой
max-age, не проверив продление сертификата и аварийные процедуры. - Добавлять
includeSubDomains, ориентируясь только наwww, и забывать о старых или внутренних именах. - Считать, что слово
preloadавтоматически добавило домен в список браузеров. - Подавать домен на preload ради оценки в сканере, не понимая сложности удаления.
- Настраивать заголовок только на успешной странице и терять его на редиректах или ошибках.
- Дублировать
Strict-Transport-Securityна CDN и origin с разными сроками. - Полагаться на очистку собственного кеша браузера как на откат для всех пользователей.
- Включать HSTS до исправления цепочки сертификата. Политика сделает ошибку TLS непреодолимой, но не устранит её.
Связанные инструменты
Анализ заголовков безопасности показывает наличие HSTS и других защитных полей. Проверка HTTP-заголовков помогает сравнить ответы разных URL и кодов, а проверка SSL-сертификата — заранее обнаружить проблемы имени или срока. Результат внешнего теста дополняйте проверкой из инфраструктуры, где завершается TLS.
Частые вопросы
Что произойдёт, если отправить HSTS по HTTP?
Браузер проигнорирует заголовок Strict-Transport-Security, полученный по незащищённому HTTP. Политику можно установить или обновить только в корректном HTTPS-ответе без ошибок TLS.
Можно ли сразу включить includeSubDomains и preload?
Технически можно, но безопаснее сначала проверить HTTPS на основном хосте и всех поддоменах, начать с короткого max-age и увеличивать его поэтапно. Preload следует рассматривать только как долгосрочное обязательство поддерживать HTTPS на всём пространстве поддоменов.
Как отключить HSTS после ошибки?
Отдайте по исправному HTTPS заголовок Strict-Transport-Security: max-age=0. Уже сохранённая политика исчезнет только после получения этого ответа; отдельные политики поддоменов и запись в preload-списке требуют самостоятельного удаления.