This article is available in Russian only. English translation is not yet available.
SSL и сайты

Что такое 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-заголовков.

Безопасное поэтапное внедрение

Практический порядок снижает радиус возможной ошибки:

  1. Составьте список основного домена и всех поддоменов, включая вложенные, внутренние и временно неиспользуемые DNS-имена. Найдите владельца и назначение каждого ресурса.
  2. Настройте HTTPS, сертификаты и HTTP-редиректы. Проверьте страницы, API, загрузки, callback-адреса и ответы с кодами ошибок. Не включайте HSTS, пока критичный сервис зависит от HTTP.
  3. Запустите основной хост с max-age=300 без includeSubDomains. Наблюдайте не меньше полного срока и проверьте поведение в нескольких браузерах.
  4. Увеличьте срок, например до суток, затем до недели. После каждого изменения ждите полный срок текущей ступени, отслеживайте ошибки TLS и готовность отката.
  5. После отдельного аудита поддоменов добавьте includeSubDomains сначала с коротким сроком. Повторите ступени и только затем переходите к месяцу и более длительному периоду.
  6. Рассматривайте годовой срок после стабильной эксплуатации. Решение о 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-списке требуют самостоятельного удаления.

Check it in practice

Related terms

Sources

  1. RFC 6797: HTTP Strict Transport Security (HSTS)
  2. MDN: Strict-Transport-Security header
  3. HSTS Preload List Submission: requirements and deployment recommendations
  4. Nginx: ngx_http_headers_module add_header directive

Как проверить SSL-сертификат сайта

Проверка сертификата не ограничивается датой окончания: важны имя узла, цепочка до доверенного центра и фактическая конфигурация TLS-сервера.