WAF на уровне веб-сервера — это быстрая первая линия защиты для сайтов на VDS. Связка ModSecurity (движок правил) и OWASP Core Rule Set (универсальный набор сигнатур и эвристик) с Nginx позволяет отсеивать типовые атаки на приложения: SQLi, XSS, RCE, LFI/RFI, HTTP-протокольные аномалии. Важно не просто «включить правила», а запустить их с учётом конкретной CMS, типов трафика и особенностей аплоадов, чтобы не попасть в ловушку ложных срабатываний и не превратить защиту в точку отказа.
Ниже — практическая инструкция: как поставить ModSecurity v3 и OWASP CRS, правильно подключить их к Nginx, безопасно перейти от режима мониторинга к блокировкам и настроить тюнинг под популярные CMS (WordPress, 1C‑Bitrix, Joomla/OpenCart). Дополнительно разберём оптимизацию производительности, логи и методику обработки false positive. Если выбираете панель для сервера — посмотрите сравнение в материале обзор VDS-панелей.
Что даёт WAF на Nginx и когда он нужен
В традиционной схеме Nginx принимает HTTP(S), проксирует в PHP‑FPM или upstream. WAF внедряется в этот путь как фильтр запросов со своими правилами. Он не заменяет исправление уязвимостей в коде, обновления CMS и плагинов, но значительно сокращает окно атаки, снижает шум и экономит время на инцидентах. Особенно это актуально для публичных сайтов, админок, API-эндпойнтов и лендингов с формами.
Правило №1: WAF запускаем сначала в режиме мониторинга (DetectionOnly). Сбор логов и разбор ложных срабатываний — потом включение блокировок. Иначе рискуете потерять конверсии и SEO из-за случайных 403.
Установка ModSecurity v3 и OWASP CRS на Debian/Ubuntu
Ниже показан путь через пакетный менеджер Debian/Ubuntu. Для других дистрибутивов команды и имена пакетов могут отличаться, но общий принцип тот же: движок ModSecurity (libmodsecurity3) + динамический модуль для Nginx + набор правил OWASP CRS.
sudo apt update && sudo apt install -y \
libmodsecurity3 \
libnginx-mod-http-modsecurity \
modsecurity-crs
Скопируйте рекомендуемый базовый конфиг ModSecurity и зафиксируйте режим DetectionOnly (переключим на On позже, когда убедимся, что правила «чистые»):
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
sudo sed -i -E 's/^SecRuleEngine .*/SecRuleEngine DetectionOnly/' /etc/modsecurity/modsecurity.conf
Подготовьте конфиг с правилами для Nginx. Создадим файл-объединение:
sudo mkdir -p /etc/nginx/modsec
sudo tee /etc/nginx/modsec/main.conf >/dev/null <<'EOF'
Include /etc/modsecurity/modsecurity.conf
# Подключаем CRS: сначала crs-setup, затем rules
Include /etc/modsecurity/crs-setup.conf
Include /usr/share/modsecurity-crs/rules/*.conf
EOF
Активируйте и настройте OWASP CRS. Скопируйте шаблон:
sudo cp /usr/share/modsecurity-crs/crs-setup.conf.example /etc/modsecurity/crs-setup.conf
Откройте /etc/modsecurity/crs-setup.conf
и задайте начальные параметры. Рекомендуемые базовые значения для старта:
tx.paranoia_level=1
— минимальный уровень строгости для старта;tx.inbound_anomaly_score_threshold=10
иtx.outbound_anomaly_score_threshold=10
— разумный баланс чувствительности;tx.allowed_methods=GET HEAD POST OPTIONS
— расширяйте под ваши API при необходимости.
Подключение к Nginx
Убедитесь, что модуль подхватывается. В /etc/nginx/nginx.conf
добавьте в самый верх (вне блока http
):
load_module modules/ngx_http_modsecurity_module.so;
Активируйте WAF в нужном сервере/локации. Пример: включить для всего сайта, а для статических файлов отключить — это экономит ресурсы и снижает риск ложных срабатываний на бинарях:
server {
listen 80;
server_name example.com;
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
location ~* \.(?:css|js|jpg|jpeg|png|gif|svg|ico|woff2?|mp4|webm|txt|xml)$ {
access_log off;
modsecurity off;
try_files $uri =404;
}
location / {
proxy_pass http://php-fpm-or-upstream;
}
}
Проверьте конфигурацию Nginx и перезапустите:
sudo nginx -t && sudo systemctl reload nginx
Первый запуск: DetectionOnly, сбор сигналов и переход к блокировкам
На этапе внедрения оставьте SecRuleEngine DetectionOnly
в /etc/modsecurity/modsecurity.conf
. Это позволит собирать события без блокировок. Дайте системе поработать под реальным трафиком хотя бы 24–72 часа, чтобы собрать статистику по ложным срабатываниям (false positive) под вашу CMS и плагины. Удобно тестировать на отдельной стейджинг-среде — для WordPress мы разбирали подход в статье стейджинг на VDS.
Где смотреть логи:
/var/log/modsec_audit.log
— аудит-лог ModSecurity (подробный, многострочный);/var/log/nginx/error.log
— краткие сообщения от модуля;- при необходимости включайте JSON-лог в отдельный файл через
SecAuditLogFormat JSON
.
Когда будете готовы включить блокировки, измените движок на On
:
sudo sed -i -E 's/^SecRuleEngine .*/SecRuleEngine On/' /etc/modsecurity/modsecurity.conf
sudo systemctl reload nginx

Тюнинг под популярные CMS
Стратегия одна: минимальные общие правила + адресные исключения под конкретные эндпойнты, где бизнес-логика «шумная» (аплоады, админка, AJAX). Не отключайте весь WAF на админке — лучше точечно убрать проблемные правила или поднять порог аномалий.
WordPress
Типичные зоны риска: /wp-admin/
, /wp-admin/admin-ajax.php
, /wp-json/
, /xmlrpc.php
(если используется). Частые ложные срабатывания появляются на правилах 942100 (SQLi), 941100 (XSS) при сложных AJAX-пейлоадах и на загрузках медиа.
Пример точечных исключений в /etc/nginx/modsec/main.conf
(делайте свои уникальные ID выше 100000):
# Белый список IP для админов (полное отключение правил для доверенных)
SecRule REMOTE_ADDR "@ipMatch 203.0.113.10,203.0.113.11" \
"id:10001,phase:1,pass,log,tag:'allowlist',ctl:ruleEngine=Off"
# Снижение шума для admin-ajax: снятие конкретных правил
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" \
"id:10002,phase:1,pass,log,ctl:ruleRemoveById=942100,ctl:ruleRemoveById=941100"
# Увеличение лимитов тела запроса для аплоадов
SecRule REQUEST_URI "@beginsWith /wp-admin/async-upload.php" \
"id:10003,phase:1,pass,log,ctl:requestBodyLimit=131072000"
Не забудьте синхронизировать лимит тела в Nginx и PHP-FPM для загрузок:
# В серверном блоке Nginx
client_max_body_size 128m;
1C‑Bitrix
Зоны: /bitrix/admin/
, /bitrix/services/
, /upload/
, интеграции CRM. Часто попадаются «шумные» запросы с сериализованными данными и нестандартными параметрами.
# Снятие подозрительных правил только на служебных путях Bitrix
SecRule REQUEST_URI "@beginsWith /bitrix/admin/" \
"id:10010,phase:1,pass,log,ctl:ruleRemoveById=942100,ctl:ruleRemoveById=941100"
# Увеличение лимита для загрузок в /upload/
SecRule REQUEST_URI "@beginsWith /upload/" \
"id:10011,phase:1,pass,log,ctl:requestBodyLimit=262144000"
Joomla / OpenCart и другие
Для Joomla обратите внимание на /administrator/
и API-плагины; для OpenCart — /admin/
и роуты, которые принимают большие JSON. Подход такой же: найти часто срабатывающие правила и снять их локально или подправить цели (targets) через SecRuleUpdateTargetById
.
# Пример: убрать инспекцию тела для конкретного правила на эндпойнте API
SecRule REQUEST_URI "@streq /api/endpoint" \
"id:10020,phase:1,pass,log,ctl:ruleRemoveById=942110"
Управление ложными срабатываниями (false positive)
Разбор FP — ключ к стабильной работе. Методика:
- Находите запись в аудит-логе с блокировкой или с высоким anomaly score.
- Определяете ID правила (например, 942100) и контекст: URI, параметр, поле формы.
- Выбираете минимально достаточную меру: снять правило на конкретном пути, убрать инспекцию конкретного параметра, либо поднять порог аномалий.
- Фиксируете исключение в
main.conf
с уникальным ID и тэгом, комментируете причину. - Перепроверяете, что исключение не расширяет поверхность атаки за пределами нужного контекста.
Примеры адресных корректировок:
# Отключить инспекцию параметра 'content' для XSS-правила 941100 на конкретном пути
SecRule REQUEST_URI "@streq /wp-json/myplugin/submit" \
"id:10100,phase:1,pass,log,ctl:ruleRemoveById=941100"
# Или сузить цели вместо снятия правила целиком
SecRuleUpdateTargetById 941100 "!ARGS:content"
Если FP много, не спешите «выкручивать» CRS до Paranoia Level 0. Лучше держать tx.paranoia_level=1
или 2 и постепенно добавлять точечные исключения. Когда шум стабилизируется, можно повысить уровень и повторить цикл.
Производительность: где экономить
WAF добавляет накладные расходы на каждый запрос. Что помогает:
- Отключать WAF на статике и кэше, как показано выше.
- Не инспектировать большие бинарные тела, где это безопасно. Используйте
ctl:requestBodyLimit
и исключения по путям. - Минимизировать глобальные отключения правил, отдавая предпочтение локальным исключениям.
- Следить за лимитами файловых дескрипторов и временем блокировок логов (в audit-логах). При необходимости уменьшайте детализацию аудита.
Дополнительно стоит ограничить «шумные» эндпойнты rate‑лимитом на уровне Nginx (например, брутфорс авторизации), но это уже отдельная тема — WAF и лимиты прекрасно дополняют друг друга.
Логирование, аудит и ротация
Для удобства разбора инцидентов используйте подробный аудит-лог. Типовая секция в /etc/modsecurity/modsecurity.conf
:
SecAuditEngine RelevantOnly
SecAuditLog /var/log/modsec_audit.log
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
# При высоких нагрузках рассмотрите Concurrent с отдельной директорией
Проверьте политику ротации логов, чтобы накопление большого файла не влияло на производительность. Тестируйте WAF простыми запросами и проверяйте логи:
curl -I "https://example.com/?id=1' or '1'='1" \
-H 'User-Agent: waf-test'
curl -I "https://example.com/?q=<script>;alert(1)</script>"
Поддержка и обновления CRS
OWASP CRS активно развивается: исправляются FP, улучшаются сигнатуры. Регулярно обновляйте пакеты дистрибутива. После обновления проверяйте диффы в crs-setup.conf
и свою зону исключений, чтобы они оставались актуальными. Хорошая практика — вести версионирование своих исключений и базового main.conf
в Git.
Чек‑лист внедрения
- Установить libmodsecurity, модуль Nginx и CRS.
- Подключить модуль в Nginx, создать
/etc/nginx/modsec/main.conf
. - Включить DetectionOnly, собрать логи 1–3 дня.
- Добавить исключения под CMS: админка, AJAX, аплоады, API.
- Отключить WAF на статике и кэше.
- Поднять пороги аномалий до 10–15 на старте, затем скорректировать.
- Переключить
SecRuleEngine On
, мониторить ошибки и бизнес-метрики. - Внести правки по свежим FP, закрепить конфиг в Git.
Откат и безопасность
Если после включения блокировок видите аномалии (растёт 403, падают конверсии), переключайтесь обратно в DetectionOnly одной правкой в modsecurity.conf
и перезагрузкой Nginx. Держите под рукой набор последних изменений, чтобы быстро сузить проблемный сегмент. Не снимайте глобально самые важные правила (SQLi/XSS) без крайней необходимости — лучше избирательно корректируйте цели и URI.
Итог: связка ModSecurity + OWASP CRS в Nginx на VDS за несколько часов даёт осязаемую защиту и управляемость рисков. Ключ к успеху — постепенное внедрение, дисциплина в разборе ложных срабатываний и аккуратные исключения под вашу CMS и плагины.