Server Warden
РУКОВОДСТВО ПО БЕЗОПАСНОСТИ СЕРВЕРА

Лучшие практики безопасности Nginx

Усиление защиты nginx означает правильную настройку TLS, отправку заголовков безопасности, которые ожидают браузеры, ограничение частоты и размера запросов, скрытие информации о версии и ведение журналов с достаточной детализацией для последующего расследования инцидентов. Ни один из этих шагов не требует замены nginx или покупки дополнительного ПО: это изменения конфигурации, которые можно внести прямо в блоки server, причём большинство из них в сумме занимают меньше часа.

Быстрый результат

  • Добавьте server_tokens off; в блок http {} и перезагрузите nginx.
  • Добавьте пять основных заголовков безопасности (см. ниже) в основной блок server.
  • Установите для client_max_body_size минимальное значение, которое реально нужно вашему приложению.
  • Добавьте правило limit_req_zone для страницы входа или административного пути.
  • Выполните nginx -t для проверки синтаксиса, затем systemctl reload nginx, чтобы применить изменения без разрыва соединений.

Настройка TLS и SSL

Безопасная конфигурация TLS в nginx поддерживает только TLS 1.2 и TLS 1.3, отключает устаревшие протоколы и слабые шифры и включает OCSP stapling. Правильная настройка этого уровня защищает все остальные уровни стека, поскольку скомпрометированный канал передачи данных подрывает и аутентификацию, и заголовки, и всё остальное.

TLS 1.0 и TLS 1.1 имеют известные слабые места, и предлагать их не следует. Mozilla SSL Configuration Generator (ssl-config.mozilla.org) — наиболее практичный способ сгенерировать конфигурацию, соответствующую вашей версии OpenSSL и нужному уровню совместимости. Его профиль Intermediate, поддерживающий TLS 1.2 и 1.3 с надёжными шифрами и при этом сохраняющий широкую совместимость с реальными браузерами и API-клиентами, — правильный выбор по умолчанию для большинства публичных сайтов. Профиль Modern ограничивает соединения только TLS 1.3 и уместен, когда вы контролируете каждый подключающийся клиент, например для внутреннего API.

Типичная конфигурация в стиле Intermediate выглядит так:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;

# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;

Всегда генерируйте список шифров именно под вашу версию nginx и OpenSSL через генератор Mozilla, а не копируйте строку шифров из старой статьи в блоге, поскольку рекомендуемые наборы шифров меняются по мере обнаружения уязвимостей. После развёртывания проверяйте результат независимым сканером (например, SSL Labs), а не полагайтесь на то, что один лишь файл конфигурации гарантирует хорошую оценку, поскольку промежуточные сертификаты, заголовки HSTS и порядок цепочки сертификатов также влияют на результат.

Заголовки безопасности

Заголовки безопасности указывают браузеру применять защиты, которые сам nginx обеспечить не может, — например, блокировку кликджекинга, MIME-sniffing и загрузки смешанного контента. По умолчанию nginx не отправляет ни один из перечисленных ниже заголовков, поэтому каждый из них нужно добавлять явно.

Проект OWASP Secure Headers Project (документационный проект, поддерживаемый OWASP, который перечисляет заголовки для добавления и удаления) рекомендует следующий базовый набор, который можно добавить внутри блока server {}:

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Resource-Policy "same-site" always;

Несколько замечаний о правильном использовании этих заголовков. Strict-Transport-Security (HSTS) указывает браузерам подключаться исключительно по HTTPS в течение заданного срока; не включайте preload, пока не убедитесь, что HTTPS поддерживают все поддомены, поскольку списки preload долго отменяются. Content-Security-Policy намеренно не включена в базовый набор выше, потому что, согласно рекомендациям OWASP, она требует настройки под конкретные скрипты, стили и сторонние ресурсы вашего сайта, а не универсального значения; неправильно настроенная CSP может нарушить работу самого сайта, поэтому выстраивайте её постепенно, сначала в режиме только отчётов (Content-Security-Policy-Report-Only), прежде чем включать принудительное применение. Параметр always гарантирует, что заголовки отправляются и в ответах с ошибками, а не только при 200 OK, что важно, поскольку атакующие часто зондируют страницы ошибок.

Не уверены, какие заголовки и настройки TLS реально использует ваш сервер?

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

Получить бесплатную проверку сервера Связаться с инженером по безопасности

Ограничение частоты запросов

Ограничение частоты запросов задаёт предел числа запросов, которые один клиент может отправить за определённое временное окно, что ослабляет атаки перебором паролей, credential stuffing и базовый DoS-трафик ещё до того, как он достигнет приложения. Согласно официальной документации nginx, эта функциональность реализована нативно через модуль ngx_http_limit_req_module, использующий алгоритм leaky bucket («дырявое ведро»).

Типичная настройка определяет зону в разделяемой памяти с ключом по IP-адресу клиента, а затем применяет её к эндпоинтам, на которые реально нацеливаются атакующие, — например, к формам входа и поиску:

http {
    limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;

    server {
        location /login {
            limit_req zone=login burst=5 nodelay;
            proxy_pass http://app_backend;
        }
    }
}

Параметр rate задаёт устойчиво допустимую частоту запросов (здесь — 5 запросов в минуту на IP). Параметр burst допускает короткую очередь дополнительных запросов сверх этой частоты, прежде чем nginx начнёт их отклонять, а nodelay обрабатывает запросы из очереди burst сразу, а не искусственно растягивает их во времени, что сохраняет комфортный опыт для легитимных пользователей, случайно кликнувших дважды. Применяйте строгие ограничения точечно — к входу, сбросу пароля, поиску и API-эндпоинтам, а не ко всему сайту, поскольку слишком агрессивный глобальный лимит будет отклонять реальных посетителей при обычных всплесках трафика. Nginx также поддерживает limit_req_dry_run on; для логирования того, что было бы ограничено, без реального применения лимита, — это полезно для настройки порогов перед включением в продакшене.

Ограничение частоты запросов на уровне веб-сервера — лишь часть более широкой защиты от объёмных атак и злоупотреблений на уровне приложения; уровни выше и ниже nginx, включая фильтрацию выше по цепочке и контроль на уровне межсетевого экрана, рассмотрены в нашем руководстве по защите от DDoS для малого бизнеса.

Скрытие server tokens и информации о версии

По умолчанию nginx отправляет точный номер версии в заголовке ответа Server и на стандартных страницах ошибок, что позволяет автоматическим сканерам сопоставлять ваш сервер с известными уязвимостями конкретной версии. Установка server_tokens off; в блоке http {} убирает номер версии из обоих мест.

http {
    server_tokens off;
}

Это не замена патчингу: настойчивый атакующий зачастую всё равно сможет определить nginx по поведению. Но эта настройка убирает бесплатный, не требующий усилий признак, на который опираются автоматические сканеры уязвимостей, а включается она одной строкой и перезагрузкой. Для более полной переработки стандартных страниц ошибок и дальнейшего снижения утечки информации специализированные руководства по усилению защиты, такие как проект анализатора безопасности nginx Gixy, описывают дополнительные приёмы удаления заголовков, но server_tokens off покрывает стандартный случай для подавляющего большинства сайтов.

Ограничение размера запросов и неиспользуемых методов

Ограничение размера тела запроса и HTTP-методов закрывает атаки на исчерпание ресурсов и сокращает то, что атакующий вообще может попытаться сделать с вашим приложением. Оба изменения делаются одной директивой.

client_max_body_size определяет максимальный размер тела запроса, который nginx примет, прежде чем вернуть ошибку 413. Если оставить значение по умолчанию nginx или повысить его без конкретной причины, атакующие (или некорректно работающие клиенты) смогут отправлять чрезмерно большие загрузки, расходующие дисковое пространство, память и время воркеров:

server {
    client_max_body_size 1m;  # raise only for endpoints that need uploads
}

location /uploads/ {
    client_max_body_size 20m;
}

Установите на уровне server минимальный лимит, который реально нужен вашему приложению, и повышайте его только внутри конкретных блоков location, которые действительно обрабатывают загрузку файлов. Это ограничивает риск одним путём, которому это нужно, вместо всего сайта.

Аналогично, если вашему сайту или API всегда нужны только GET, HEAD и POST, остальные методы можно явно отклонять:

location / {
    if ($request_method !~ ^(GET|HEAD|POST)$) {
        return 405;
    }
}

Обратите внимание, что документация nginx в целом не рекомендует использовать if внутри блоков location, за исключением узкого набора случаев, подобных этому, поскольку у if есть известные неожиданные взаимодействия с другими директивами; держите такие блоки простыми и после любых изменений проверяйте их командой nginx -t.

Отключение неиспользуемых модулей

Каждый вкомпилированный модуль nginx — это дополнительный код, который может содержать ошибки или быть неправильно настроен, поэтому удаление неиспользуемых модулей снижает поверхность атаки, даже если ни один из них сейчас не эксплуатируется. Это касается этапа сборки, а не только уровня конфигурации.

Если вы собираете nginx из исходников или используете пакет с настраиваемым набором модулей, отключайте те, которые не используете, — например, WebDAV (ngx_http_dav_module), autoindex, если листинг каталогов не нужен, или модуль SSI, если вы не используете server-side includes. Проверить список скомпилированных модулей можно командой:

nginx -V 2>&1 | tr ' ' '\n' | grep module

На уровне конфигурации тот же принцип применим к autoindex: если оставить листинг каталогов включённым на пути, который не должен просматриваться, это может раскрыть имена файлов и структуру, которые вы не собирались публиковать. Явно установите autoindex off; (значение по умолчанию в nginx) и подтвердите это в конфигурации, а не полагайтесь на то, что оно и так отключено, — особенно для любого блока location, отдающего статические файлы или загрузки.

Формат логов для видимости с точки зрения безопасности

Полезный с точки зрения безопасности формат логов nginx фиксирует IP-адрес клиента, время запроса, код статуса и время обработки, а не только минимум, необходимый для подсчёта хитов. Формат combined, используемый по умолчанию, — разумная отправная точка, но он не содержит данных о времени, которые помогают отличить обычный трафик от автоматизированных злоупотреблений или атак в стиле slow-loris.

Более ориентированный на безопасность пользовательский формат добавляет $request_time (общее время, которое nginx потратил на обработку запроса) к стандартным полям:

log_format security '$remote_addr - $remote_user [$time_local] '
                     '"$request" $status $body_bytes_sent '
                     '"$http_referer" "$http_user_agent" '
                     'rt=$request_time';

access_log /var/log/nginx/access.log security;

$request_time стоит добавлять практически в любом развёртывании, поскольку это поле показывает время обработки запроса nginx с точностью до миллисекунды, что помогает выявлять как проблемы производительности, так и определённые шаблоны атак — например, поток запросов, каждый из которых дёшев по отдельности, но в совокупности перегружает сервер. Логи полезны только тогда, когда их кто-то реально просматривает; сами по себе access- и error-логи, лежащие на диске, ничего не обнаруживают. Наше сопутствующее руководство по мониторингу сервера и анализу логов рассказывает, как превратить эти данные логов в реальный сигнал раннего предупреждения, включая их централизацию и отделение настоящих инцидентов от рутинного шума.

Полную картину того, как усиление защиты nginx вписывается в общую безопасность VPS — от SSH и межсетевого экрана до резервного копирования, — смотрите в чек-листе безопасности VPS. Если nginx работает за межсетевым экраном, который вы давно не пересматривали, наше руководство по межсетевому экрану Linux рассматривает уровень непосредственно под ним.

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

Какая настройка безопасности nginx самая важная?

Единой самой важной настройки не существует, но современная конфигурация TLS (только TLS 1.2 и 1.3, надёжные шифры) в сочетании с server_tokens off и правилом ограничения частоты запросов для страниц входа или поиска даёт максимальный эффект при минимальных усилиях.

Действительно ли server_tokens off останавливает атаки?

Сам по себе — нет. Эта настройка убирает номер версии nginx из заголовка Server и со стандартных страниц ошибок, что немного усложняет автоматическим сканерам определение точной версии сервера и сопоставление её с известными уязвимостями, но она не устраняет уязвимости и не блокирует трафик сама по себе.

Какой профиль TLS от Mozilla использовать — Modern или Intermediate?

Для большинства публичных сайтов правильный выбор по умолчанию — профиль Intermediate из Mozilla SSL Configuration Generator, поскольку он поддерживает TLS 1.2 и 1.3 с надёжными шифрами, оставаясь совместимым с браузерами и API-клиентами, которые реально используют ваши посетители. Профиль Modern (только TLS 1.3) уместен, когда вы контролируете каждый клиент, подключающийся к серверу.

Как настроить ограничение частоты запросов в nginx, не нарушив легитимный трафик?

Используйте модуль ngx_http_limit_req_module с консервативным значением rate для чувствительных эндпоинтов, таких как вход и поиск, и задайте значение burst с nodelay, чтобы короткие обычные всплески трафика поглощались, а не отклонялись сразу. Применяйте самые строгие ограничения именно к тем эндпоинтам, на которые реально нацеливаются атакующие, а не ко всему сайту.

Нужен ли мне Web Application Firewall (WAF) в дополнение к усилению защиты nginx?

Усиление конфигурации nginx и использование WAF решают задачи на разных уровнях. Усиление конфигурации уменьшает поверхность атаки и утечку информации самим веб-сервером; WAF анализирует содержимое запросов на предмет известных шаблонов атак. Многие небольшие компании начинают с усиления защиты и мониторинга, а WAF или управляемую защиту добавляют, когда это оправдано объёмом трафика и уровнем риска.

Какое максимальное безопасное значение для client_max_body_size?

Универсального числа не существует. Самый безопасный подход — задать client_max_body_size настолько низким, насколько это реально необходимо вашему приложению (например, 1m для сайта только с формами или больше для загрузки файлов), вместо того чтобы оставлять значение по умолчанию nginx или бесконечно его повышать, поскольку слишком большие тела запросов — распространённый вектор исчерпания ресурсов и злоупотреблений.

Как часто нужно пересматривать конфигурацию безопасности nginx?

Пересматривайте её при каждом обновлении nginx, при добавлении новых поддоменов или приложений за ним, и как минимум раз в несколько месяцев, поскольку рекомендации по шифрам TLS и заголовкам от таких источников, как Mozilla и OWASP, со временем меняются по мере обнаружения новых уязвимостей.

Не уверены, в каком состоянии ваш сервер?

Получите бесплатную проверку безопасности только для чтения или обратитесь к инженеру по безопасности по вопросам управляемой защиты.

Получить бесплатную проверку сервера Связаться с инженером по безопасности