Категория: Веб-сервер и инфраструктураОбновлено 2026-10-27

Security headers (заголовки безопасности)

Security headers (заголовки безопасности) это HTTP заголовки ответа, такие как Strict-Transport-Security или X-Content-Type-Options, указывающие браузеру применять дополнительную защиту сверх того, что делает сам сервер.

Заголовки безопасности и подводные камни: HSTS, nosniff, CSP, add_header с always, наследование и устаревший заголовок XSS
Эти заголовки применяет браузер, поэтому сервер должен отправлять их в каждом ответе, включая страницы ошибок.

Почему браузеры, а не сервер, применяют эти защиты

Security headers работают, давая браузеру посетителя инструкцию применить дополнительные защиты, например отказаться загружать страницу по обычному HTTP или блокировать определённые типы встраиваемого контента, а не делая что-либо на стороне сервера сверх отправки этой инструкции.

Самые частые отсутствующие

Strict-Transport-Security, принуждающий HTTPS при будущих визитах, и X-Content-Type-Options, не позволяющий браузерам угадывать тип файла способом, который можно использовать во вред, часто отсутствуют даже на в остальном хорошо настроенных серверах.

Какие заголовки добавить и как их проверить, перечислено здесь: руководство по безопасности nginx.

Как проверить, что сервер отдаёт на самом деле

Не верьте файлу конфигурации, проверяйте то, что уходит по сети. Выведите заголовки ответа для обычной страницы и для несуществующей:

curl -s -D - -o /dev/null https://example.com/
curl -s -D - -o /dev/null https://example.com/no-such-page

Второй запрос важен из-за того, как работает add_header в nginx. Без параметра always заголовок добавляется только к ответам с кодами 200, 201, 204, 206, 301, 302, 303, 304, 307 и 308, поэтому страницы 404 и 500 уходят без него. Вторая классическая ловушка это наследование: директивы add_header наследуются с предыдущего уровня, только если на текущем уровне их нет. Одна строка add_header Cache-Control внутри location молча отбрасывает все заголовки безопасности, заданные на уровне server, для этого location. Повторите заголовки там либо в nginx 1.29.3 и новее используйте add_header_inherit merge;. Проверяйте важные разделы (вход, статику, API), а не только главную страницу.

У проекта OWASP Secure Headers есть и подпроект с валидатором, если нужен перечень для сверки. Сам базовый набор заголовков приведён в руководстве по безопасности nginx.

Как внедрять HSTS и CSP, не заблокировав себя

Два заголовка требуют поэтапного внедрения. Браузеры кэшируют политику Strict-Transport-Security на max-age секунд, и, по данным MDN, значение max-age=0 вступает в силу только после очередного защищённого запроса браузера. Поэтому ошибку исправлять долго: начните с короткого значения и увеличивайте его, когда все поддомены заработают по HTTPS. По обычному HTTP браузеры заголовок игнорируют, а до первого защищённого визита он ничего не меняет. Для предзагрузки (preload) нужны includeSubDomains и max-age не менее 31536000 (один год).

Для Content-Security-Policy сначала отправляйте Content-Security-Policy-Report-Only. Согласно руководству MDN по CSP, нарушения при этом только регистрируются, ничего не блокируется, а политика с default-src или script-src останавливает встроенные скрипты, если у них нет nonce или хеша, и именно это чаще всего ломает сайты.

Наконец, уберите лишнее. X-Content-Type-Options: nosniff по-прежнему стоит отправлять, а вот X-XSS-Protection в MDN помечен как устаревший и нестандартный, и вместо него предлагается строгая CSP. Заголовки работают в паре с исправным TLS, от которого они зависят.

Связанные термины: TLS / SSL, nginx, server_tokens, WAF, HSTS (строгая транспортная безопасность HTTP), CORS (cross-origin resource sharing).

Часто задаваемые вопросы

Заменяют ли security headers необходимость в TLS?

Нет. Несколько security headers, например Strict-Transport-Security, конкретно зависят от уже настроенного TLS; они усиливают его, а не заменяют.

Как проверить, какие security headers сайт отправляет сейчас?

Инструменты разработчика в браузере показывают заголовки ответа напрямую, а несколько бесплатных онлайн-инструментов сканирования заголовков резюмируют, что присутствует и что обычно рекомендуется, но отсутствует.

Может ли добавление security headers сломать существующий сайт?

Иногда, если заголовок вроде Content-Security-Policy слишком строгий для того, как сайт реально загружает свои ресурсы; заголовки нужно тестировать, а не бездумно копировать из общего шаблона.

Почему заголовка безопасности нет на страницах ошибок?

В nginx add_header применяется только к фиксированному списку кодов успеха и перенаправления, если не указан параметр always. Добавьте always к каждому заголовку, чтобы он отдавался и в ответах 404 и 500.

Нужно ли по-прежнему отправлять X-XSS-Protection?

Нет. MDN помечает его как устаревший и нестандартный и рекомендует вместо него Content-Security-Policy. Оставьте X-Content-Type-Options: nosniff, он по-прежнему полезен.

Хотите увидеть, в каком состоянии ваш сервер?

Запустите бесплатную read-only проверку сервера или откройте Security Lab и посмотрите цикл обнаружение, сдерживание, восстановление, проверка в действии.

Получить бесплатную проверку сервераОткрыть Security Lab