Ошибки конфигурации HSTS: чеклист перед включением

HSTS усиливает HTTPS, но фиксирует политику в браузере на длительный срок. Проверяем сертификаты, поддомены, max-age, includeSubDomains и preload до включения.

HSTS нельзя включать как обычный «полезный заголовок» сразу на год и для всех поддоменов. Браузер запоминает политику и затем сам заменяет HTTP на HTTPS; при ошибке сертификата пользователь не должен получать обычную возможность продолжить небезопасное соединение. Поэтому безопасный порядок такой: **сначала исправить HTTPS на всём выбранном охвате, затем включить короткий max-age, увеличить его после наблюдения и только отдельно решить вопрос includeSubDomains и preload**.

Базовый заголовок выглядит так:

Strict-Transport-Security: max-age=300

Пять минут — пример стартового окна, а не универсальная рекомендация для production. Итоговое значение выбирают по готовности инфраструктуры и процедуре отката.

Что HSTS делает — и чего не делает

Получив корректный заголовок по защищённому соединению, совместимый браузер запоминает политику для hostname. Следующие обращения по http:// он преобразует в https:// до отправки HTTP-запроса. Согласно RFC 6797, заголовок, полученный по незащищённому HTTP, браузер должен игнорировать: иначе атакующий в сети мог бы подменить политику.

HSTS не выпускает сертификат, не чинит TLS, не устраняет mixed content и не настраивает редиректы для клиентов без сохранённой политики. Он усиливает уже работающий HTTPS. Если сертификат истёк или не подходит имени, HSTS делает проблему заметнее и жёстче, а не исправляет её.

Семь примеров неправильной конфигурации

1. Большой max-age в первый релиз

Strict-Transport-Security: max-age=31536000

Синтаксис допустим, но запуск рискованный, если HTTPS ещё не прошёл проверку на продлении сертификата, резервном балансировщике и аварийном переключении. Уже получившие заголовок браузеры могут хранить политику до истечения срока. Уменьшение значения на сервере поможет только после следующего успешного HTTPS-ответа клиента.

Как лучше: начать с короткого окна, проверить логи и сертификаты, затем повышать срок ступенями.

2. includeSubDomains без инвентаризации

Strict-Transport-Security: max-age=31536000; includeSubDomains

Директива распространяет политику на поддомены. Сломаться может забытый old.example.ru, панель оборудования, callback партнёра или делегированный клиентский hostname, где HTTPS отсутствует либо сертификат неверен.

Сначала соберите DNS-имена, CNAME, делегации и внешних владельцев сервисов. Для каждого имени подтвердите HTTPS и право команды управлять им.

3. Заголовок отправляется только по HTTP

HTTP/1.1 301 Moved Permanently
Location: https://example.ru/
Strict-Transport-Security: max-age=31536000

Если это именно незащищённый HTTP-ответ, браузер не должен принимать из него HSTS. Политику нужно отправлять в HTTPS-ответе. HTTP-редирект на HTTPS всё равно нужен для первого посещения клиента без заранее известной политики, если домен не находится в preload-списке.

4. HSTS включён только на одной странице

Заголовок есть на /, но отсутствует на ответах API, ошибках прокси или другом HTTPS virtual host. Политика хранится для hostname, поэтому один успешный ответ уже может её установить. Но непоследовательность выдаёт разные конфигурационные ветки и затрудняет контроль/откат.

Как лучше: добавлять заголовок на уровне единого HTTPS ingress для выбранного hostname и тестировать обычный ответ, редирект и типовую ошибку. Не полагайтесь на HTML <meta http-equiv>: RFC 6797 требует игнорировать HSTS, объявленный через meta-элемент.

5. Дублирующиеся или конфликтующие заголовки

Strict-Transport-Security: max-age=300
Strict-Transport-Security: max-age=31536000; includeSubDomains

RFC описывает обработку нескольких полей как некорректную ситуацию: клиент должен обрабатывать только одно поле STS. Не рассчитывайте, что браузер «выберет безопасный вариант». Источником дубля часто становятся CDN и origin, где заголовок добавлен независимо.

Как лучше: назначить одного владельца политики и проверять итоговый ответ снаружи, после CDN и балансировщика.

6. preload добавлен как декоративная директива

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Само слово preload в заголовке не добавляет домен в браузерный список. Для этого нужна отдельная заявка и выполнение требований оператора preload-списка. Попадание в список меняет первый визит: браузер знает политику заранее. Удаление тоже требует процесса и не происходит мгновенно во всех установленных версиях браузеров.

Как лучше: рассматривать preload как отдельный проект после стабильной работы HSTS на всём доменном дереве. Не включать его только ради высокого балла сканера.

7. HSTS используется вместо мониторинга сертификата

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

Как лучше: отдельно контролировать срок сертификата, соответствие имени, цепочку и доступность HTTPS снаружи.

Чеклист до первого включения

HTTPS и сертификаты

  • [ ] HTTP для основного hostname перенаправляет на канонический HTTPS URL.
  • [ ] Каждый hostname в планируемом охвате открывается по HTTPS.
  • [ ] Сертификат действителен, доверен и содержит нужные DNS-имена.
  • [ ] Полная цепочка отдаётся на основном и резервном ingress.
  • [ ] Автопродление проверено не только «по настройке», но и наблюдаемым успешным выпуском/тестом.
  • [ ] Аварийный CDN, балансировщик или origin имеют рабочий сертификат до переключения.

Инвентаризация домена

  • [ ] Собраны A/AAAA, CNAME, делегированные зоны и внешние SaaS.
  • [ ] Проверены www, API, legacy и технические поддомены.
  • [ ] Для исключений принято решение до includeSubDomains, а не после инцидента.

Выдача заголовка

  • [ ] Strict-Transport-Security приходит по HTTPS.
  • [ ] В итоговом ответе ровно одно поле HSTS.
  • [ ] max-age — неотрицательное целое число секунд.
  • [ ] Заголовок одинаково контролируется после CDN/reverse proxy.
  • [ ] Проверены 200, редиректы и типовые ответы ошибок.
  • [ ] Политика не пытается задаваться только через HTML meta.

Эксплуатация и откат

  • [ ] Есть владелец сертификатов и HSTS-конфигурации.
  • [ ] Настроено оповещение до истечения сертификата.
  • [ ] Описано, как быстро выпустить/заменить сертификат и вернуть HTTPS.
  • [ ] Команда понимает: max-age=0 удаляет сохранённую политику только после корректного HTTPS-ответа.
  • [ ] Учтено наследование: если родительский домен уже прислал includeSubDomains, собственный max-age=0 на поддомене не отменяет политику родителя.
  • [ ] Изменение проверяется с чистого клиента и с клиента, уже запомнившего HSTS.

Безопасная схема внедрения

Этап 1. Аудит без HSTS

Проверьте все имена, TLS, редиректы, mixed content, CDN и резервный маршрут. Исправьте инфраструктуру до включения политики.

Этап 2. Короткий срок без поддоменов

Отдайте, например, max-age=300 только на основном hostname. Убедитесь, что заголовок приходит с внешней стороны и не дублируется. Подождите больше выбранного окна и проведите тест отказа/отката.

Этап 3. Постепенное увеличение

Увеличивайте срок последовательно: часы, дни, затем целевой период. Конкретные ступени определяет ваш цикл релиза и скорость реакции. Смысл не в магических числах, а в том, чтобы ошибка успела проявиться до долгого закрепления политики.

Этап 4. Отдельное решение по includeSubDomains

Добавляйте директиву только после подтверждения HTTPS для всего доменного дерева. Если часть поддоменов принадлежит другим командам или клиентам, оцените возможность организационно гарантировать TLS на них в будущем.

Этап 5. Отдельное решение по preload

Проверьте актуальные требования сервиса preload, последствия для всех поддоменов и процедуру удаления. Preload оправдан, когда защита первого обращения важна, а организация готова постоянно поддерживать HTTPS во всём заявленном охвате.

Как проверить итоговый ответ

curl -sS -I https://example.ru/ | grep -i '^strict-transport-security:'

Проверьте также редирект и ответ без HEAD, потому что разные маршруты прокси могут иметь разные правила:

curl -sS -D - -o /dev/null https://example.ru/not-found-test
curl -sS -D - -o /dev/null http://example.ru/

Команды не показывают HSTS-хранилище браузера. Для приёмки получите политику по HTTPS на тестовом клиенте, затем откройте HTTP URL и проверьте переход.

Главное ограничение

Быстрый откат заголовка не гарантирует мгновенный откат у всех клиентов. Пользователь, который не может установить корректное HTTPS-соединение, не получит новый max-age=0. Поэтому основной план восстановления — вернуть валидный HTTPS, а не надеяться снять HSTS через сломанный канал.

Если в доменной зоне много legacy-сервисов, CDN и разных владельцев, **отправьте запрос в поддержку Web‑Puls перед включением includeSubDomains или preload**: техническая проверка внешнего HTTPS и сертификатов поможет собрать факты для решения. Сам HSTS настраивается на вашем сервере или CDN; обращение не заменяет инвентаризацию и контроль конфигурации.

Источники

SSL и сертификаты

HSTS повышает безопасность HTTPS, но при ошибке сертификата сайт может оказаться полностью заблокирован для посетителя. Разбираем, что проверить владельцу и как не пропустить проблему.

Проверьте SSL-сертификат своего сайта

Введите адрес: Web-Puls покажет срок действия, совпадение домена, доверие цепочки и базовые TLS-ошибки.

Разовая проверка доступна без регистрации. Для предупреждений об окончании срока подключите мониторинг.

Проверили SSL — что дальше?

Если сертификат исправен, подключите постоянный контроль срока. Web-Puls сохранит историю и заранее предупредит о риске окончания.