Nginx принимает на себя первый удар: все запросы к вашим сервисам проходят через него до того, как попасть в приложение. Ошибка в конфигурации означает прямой доступ к внутренним данным, перехват трафика или отказ в обслуживании. В 2026 году базовой настройки HTTPS недостаточно, нужен системный аудит: проверка TLS, защитных заголовков и правил доступа. Эта статья даёт пошаговый план с готовыми конфигурациями и командами для самостоятельной проверки без риска для рабочей среды.
Вы выполните аудит по четырём направлениям: соберёте текущую конфигурацию, проверите параметры TLS, добавите защитные HTTP-заголовки и ограничите доступ к чувствительным разделам. Каждый шаг проверяется командами, которые можно запустить прямо сейчас. Если вы настраиваете Nginx впервые, начните с разбора модулей Nginx, чтобы понимать, какие возможности доступны в вашей сборке.
Подготовка к аудиту: инструменты и исходные данные
Перед изменениями зафиксируйте текущее состояние. Это позволит откатиться, если новая конфигурация нарушит работу сервиса. Сохраните полный вывод конфигурации, список модулей и версию сервера.
Сбор информации о текущей конфигурации
Команда nginx -T выводит полную конфигурацию со всеми подключёнными файлами. Это главный источник для анализа. Выполните на сервере:
nginx -T > /root/nginx_audit_$(date +%F).conf
nginx -V 2>&1 | tee /root/nginx_modules_$(date +%F).txt
nginx -v 2>&1 | tee /root/nginx_version_$(date +%F).txt
Первая команда сохраняет конфигурацию, вторая показывает версию и параметры сборки, включая подключённые модули, третья фиксирует номер версии. Проверьте, что в выводе nginx -V есть модули http_ssl_module, http_v2_module, http_v3_module (для QUIC) и http_realip_module. Если какого-то модуля нет, часть рекомендаций из этой статьи потребует пересборки Nginx.
Сделайте резервную копию каталога конфигурации:
cp -a /etc/nginx /etc/nginx.backup.$(date +%F)
Выбор инструментов для автоматизированной проверки
Ручная проверка каждой директивы занимает часы. Автоматические сканеры ускоряют процесс и выявляют неочевидные проблемы. Основной набор для аудита Nginx в 2026 году:
- testssl.sh - проверяет TLS-конфигурацию: протоколы, шифры, сертификаты, уязвимости. Запускается одной командой:
./testssl.sh https://example.com. Вывод содержит рейтинг по каждому параметру. - nmap - сканирует открытые порты и определяет службы:
nmap -sV -p 80,443 example.com. Показывает, какие порты реально открыты снаружи. - Mozilla Observatory - онлайн-проверка защитных заголовков и общей безопасности HTTP. Даёт оценку от F до A+.
- SSL Labs - глубокий анализ TLS-стека, совместимости с клиентами и цепочек сертификатов. Эталон для проверки HTTPS.
Запустите все четыре инструмента до внесения изменений и сохраните результаты. После настройки повторите проверку и сравните показатели. Это даст объективную картину прогресса.
Аудит и настройка TLS
TLS защищает данные между клиентом и сервером. Слабые протоколы и шифры позволяют расшифровать трафик или понизить соединение до небезопасного. В 2026 году допустимы только TLS 1.2 и TLS 1.3. SSLv3, TLS 1.0 и TLS 1.1 отключены во всех современных браузерах и должны быть запрещены на сервере.
Проверка поддерживаемых протоколов и шифров
Проверьте каждый протокол отдельно с помощью openssl s_client:
openssl s_client -connect example.com:443 -tls1_2 -brief
Если первые две команды возвращают сертификат и строку «Protocol version», протоколы работают. Третья команда должна завершиться ошибкой «unsupported protocol» или «handshake failure». Если TLS 1.1 всё ещё принимается, это критическая уязвимость.
Для полного списка шифров используйте testssl.sh:
./testssl.sh --protocols --cipher-per-proto https://example.com
В выводе ищите шифры с пометкой «offered». Убедитесь, что отсутствуют: экспортные шифры (EXPORT), статические RSA (RSA-PSK, RSA-AES), CBC-шифры в TLS 1.2, а также шифры с ключами меньше 128 бит. Допустимые наборы: ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-RSA-AES128-GCM-SHA256, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-RSA-AES256-GCM-SHA384, ECDHE-ECDSA-CHACHA20-POLY1305, ECDHE-RSA-CHACHA20-POLY1305.
Оптимизация конфигурации TLS в Nginx
Проверенный блок для Nginx 1.24+ в 2026 году:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
Разбор параметров:
- ssl_protocols - разрешает только TLS 1.2 и 1.3. Всё старше отключено.
- ssl_ciphers - список шифров с прямой секретностью (ECDHE) и аутентифицированным шифрованием (GCM, CHACHA20). Порядок не критичен при
ssl_prefer_server_ciphers off, так как в TLS 1.3 выбор делает клиент. - ssl_prefer_server_ciphers off - в TLS 1.3 эта директива не работает, а для TLS 1.2 клиентские предпочтения часто дают лучшую совместимость с современными браузерами.
- ssl_session_cache - кэш сессий на 10 мегабайт. Ускоряет повторные подключения и снижает нагрузку на CPU.
- ssl_session_tickets off - отключает session tickets, которые могут быть скомпрометированы при утечке ключа. Кэш сессий достаточен.
- ssl_stapling - включает OCSP stapling: сервер сам передаёт статус отзыва сертификата, клиенту не нужно обращаться к OCSP-серверу. Это ускоряет соединение и повышает приватность.
- ssl_dhparam - файл с параметрами Диффи-Хеллмана. Сгенерируйте его командой
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048. Без этого файла Nginx использует встроенные параметры 1024 бита, что недостаточно.
После изменения конфигурации проверьте синтаксис и перезагрузите Nginx:
nginx -t && systemctl reload nginx
Настройка HSTS (HTTP Strict Transport Security)
HSTS заставляет браузер всегда использовать HTTPS для вашего домена, даже если пользователь вводит http:// или переходит по http-ссылке. Заголовок добавляется в блок server, слушающий порт 443:
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
Параметры:
- max-age=63072000 - срок действия политики в секундах (2 года).
- includeSubDomains - распространяет политику на все поддомены.
- preload - разрешает включение в список предзагрузки HSTS браузеров. Добавляйте этот параметр только если уверены, что весь домен и все поддомены будут работать по HTTPS постоянно. Удаление из списка preload занимает месяцы.
Если вы управляете несколькими сервисами через Nginx, ознакомьтесь с готовыми конфигурациями HTTPS для Nginx и Apache, где HSTS и CSP разобраны в связке с WAF.
Настройка защитных HTTP-заголовков
Заголовки безопасности управляют поведением браузера: что можно загружать, как обрабатывать ответы, какие API доступны странице. Без них браузер применяет разрешительные настройки по умолчанию, что открывает векторы для XSS, clickjacking и утечек данных.
Content-Security-Policy (CSP)
CSP ограничивает источники, из которых браузер может загружать скрипты, стили, изображения и другие ресурсы. Это основная защита от XSS: даже если злоумышленник внедрит скрипт в страницу, браузер не выполнит его, если источник не разрешён политикой.
Базовая политика для статического сайта:
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'" always;
Для приложения с внешними сервисами добавьте нужные домены в соответствующие директивы. Например, для Google Fonts:
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' https://fonts.gstatic.com;
Тестируйте политику в режиме Content-Security-Policy-Report-Only перед включением. Браузер будет сообщать о нарушениях, но не блокировать ресурсы. Настройте приём отчётов через директиву report-uri или report-to. После устранения всех нарушений замените заголовок на принудительный.
Другие важные заголовки: X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy
Каждый заголовок закрывает конкретный вектор атаки:
- X-Frame-Options - запрещает встраивание страницы во фреймы на чужих сайтах. Защита от clickjacking. Значение
SAMEORIGINразрешает фреймы только с вашего домена,DENYзапрещает полностью. - X-Content-Type-Options - значение
nosniffзапрещает браузеру угадывать MIME-тип. Без этого заголовка браузер может выполнить загруженный файл как скрипт, если сервер отдал неверный Content-Type. - Referrer-Policy - управляет передачей заголовка Referer при переходах. Значение
strict-origin-when-cross-originпередаёт только домен при переходе на другой сайт и полный URL при переходе внутри вашего домена. - Permissions-Policy - отключает доступ к API браузера: геолокация, микрофон, камера, USB. Значение
geolocation=(), microphone=(), camera=()запрещает доступ для всех источников.
Готовый блок для добавления в server:
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), usb=()" always;
Директива always обязательна: без неё заголовки добавляются только к ответам с кодом 200, но не к ошибкам 404 или 500. Злоумышленник может использовать страницы ошибок для обхода защиты.
Проверка заголовков с помощью онлайн-сервисов
После добавления заголовков проверьте их применение через комплексный аудит безопасности или напрямую:
curl -I https://example.com | grep -E 'strict-transport|content-security|x-frame|x-content|referrer|permissions'
Mozilla Observatory покажет оценку от F до A+ и список недостающих заголовков. securityheaders.com даёт отдельную оценку по заголовкам. Обе проверки бесплатны и не требуют регистрации.
Контроль доступа: ограничение по IP и аутентификация
Административные панели, статусные страницы и внутренние API не должны быть доступны всем. Nginx умеет ограничивать доступ на уровне location: по IP-адресам, по логину и паролю, по частоте запросов.
Ограничение доступа по IP-адресам
Для раздела /admin, доступного только из офисной сети:
location /admin {
allow 192.168.1.0/24;
allow 10.0.0.5;
deny all;
}
Директивы allow и deny обрабатываются по порядку. Первое совпадение определяет результат. Поэтому deny all должен быть последним. Для IPv6 используйте подсети вида 2001:db8::/32.
Ограничение по IP не работает, если пользователи заходят через прокси или VPN с динамическими адресами. В этом случае комбинируйте его с аутентификацией. Если Nginx стоит за балансировщиком, настройте модуль http_realip_module, чтобы Nginx видел реальные IP клиентов, а не адрес балансировщика.
Базовая HTTP-аутентификация
Дополнительный уровень защиты для чувствительных разделов. Создайте файл паролей:
htpasswd -c /etc/nginx/.htpasswd admin
Команда запросит пароль и создаст файл. Для добавления новых пользователей используйте htpasswd /etc/nginx/.htpasswd username без флага -c.
Подключите аутентификацию к location:
location /status {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
stub_status on;
}
Базовая аутентификация передаёт пароль в base64, что равносильно открытому тексту. Используйте её только поверх HTTPS. Для более надёжной защиты рассмотрите JWT-аутентификацию через модуль auth_jwt, доступный в Nginx 1.22+.
Защита от подбора паролей и брутфорса
Ограничение частоты запросов к формам входа снижает эффективность перебора. Определите зону лимита в блоке http:
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
Примените зону к location с формой входа:
location /login {
limit_req zone=login burst=3 nodelay;
proxy_pass http://backend;
}
Параметры: rate=5r/m - 5 запросов в минуту с одного IP, burst=3 - допускает кратковременный всплеск до 3 запросов сверх лимита, nodelay - обрабатывает всплеск без задержки. При превышении лимита Nginx возвращает 503.
Дополнительные меры защиты от распространенных атак
Базовые настройки TLS и заголовков закрывают основные векторы, но Nginx уязвим к перегрузке и разведке. Следующие меры снижают поверхность атаки.
Ограничение частоты запросов (Rate Limiting)
Глобальный лимит защищает от DDoS и сканирования. Определите зону для всего сервера:
limit_req_zone $binary_remote_addr zone=general:10m rate=30r/s;
Примените в server или location:
limit_req zone=general burst=20 nodelay;
Для API с высоким трафиком создайте отдельную зону с большим лимитом. Для статики лимит можно не применять, так как она отдаётся из кэша и не нагружает бэкенд.
Скрытие информации о сервере
Заголовок Server: nginx/1.24.0 сообщает злоумышленнику точную версию, что упрощает поиск эксплойтов. Отключите версию:
server_tokens off;
После этого заголовок будет выглядеть как Server: nginx. Для полного удаления или замены заголовка используйте модуль headers_more:
more_set_headers "Server: web";
Модуль headers_more не входит в стандартную сборку и требует пересборки Nginx. Если вы не готовы к этому, ограничьтесь server_tokens off.
Фильтрация подозрительных запросов
Простые правила блокируют известные паттерны SQL-инъекций и XSS до того, как запрос попадёт в приложение:
if ($request_uri ~* "(union.*select|select.*from|insert.*into|drop.*table|--)") {
return 403;
}
if ($request_uri ~* "(
Эти правила дают ложные срабатывания на легитимных запросах, содержащих подстроки в параметрах. Тестируйте на реальном трафике и ведите журнал блокировок. Для серьёзной фильтрации используйте ModSecurity или WAF-конфигурации для Nginx, которые разбирают запросы по стандартным правилам OWASP.
Автоматизация аудита и постоянный мониторинг
Разовый аудит фиксирует состояние на момент проверки. Безопасность требует регулярного повторения: конфигурации меняются, появляются новые уязвимости, старые настройки устаревают. Автоматизация снижает трудозатраты и гарантирует, что проверка не будет забыта.
Создание скрипта для регулярной проверки
Скрипт запускает testssl.sh и сохраняет результаты с датой:
#!/bin/bash
DOMAIN="example.com"
OUTPUT_DIR="/var/log/nginx-audit"
DATE=$(date +%F)
mkdir -p $OUTPUT_DIR
/opt/testssl.sh/testssl.sh --quiet --json-pretty https://$DOMAIN > $OUTPUT_DIR/tls_$DATE.json
/opt/testssl.sh/testssl.sh --quiet --headers https://$DOMAIN > $OUTPUT_DIR/headers_$DATE.txt
find $OUTPUT_DIR -name "*.json" -mtime +30 -delete
echo "Audit completed: $DATE" | systemd-cat -t nginx-audit
Добавьте задачу в cron:
0 3 * * 1 /usr/local/bin/nginx-audit.sh
Скрипт выполняется каждый понедельник в 3 часа ночи. Результаты хранятся 30 дней. Для отправки на почту добавьте вызов mailx или интеграцию с вашей системой оповещений.
Интеграция с CI/CD
Проверка конфигурации перед деплоем предотвращает попадание ошибок в production. Минимальный шаг в пайплайне:
nginx -t -c /etc/nginx/nginx.conf
Для проверки безопасности используйте контейнер с testssl.sh, который запускается против тестового окружения. Если оценка ниже заданного порога, деплой блокируется. Это гарантирует, что изменения конфигурации не ухудшат безопасность.
Если вы разворачиваете Nginx в облаке, рассмотрите Timeweb Cloud с готовыми образами и автоматическим масштабированием. Для доступа к API нейросетей, которые могут помочь в анализе логов, используйте AiTunnel с единым интерфейсом для 200+ моделей.
Заключение: чек-лист безопасности Nginx
Пройдите по пунктам и отметьте выполненные. Каждый пункт проверяется командами из соответствующих разделов.
- TLS 1.2 и TLS 1.3 включены, старые протоколы отключены.
- Шифры только ECDHE с GCM или CHACHA20, без CBC и статических RSA.
- HSTS добавлен с max-age не менее 1 года.
- CSP настроен и протестирован в report-only режиме.
- X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy добавлены.
- Доступ к /admin, /status и другим чувствительным разделам ограничен по IP или паролю.
- Rate limiting включён для форм входа и API.
- server_tokens off скрывает версию Nginx.
- Автоматический аудит запускается по расписанию.
- Проверка конфигурации встроена в CI/CD.
Повторяйте аудит не реже одного раза в квартал или после каждого значительного изменения конфигурации. Безопасность Nginx - это процесс, а не разовое действие. Начните с hardening Linux-сервера, на котором работает Nginx, чтобы закрыть уязвимости уровня операционной системы.