OSEN-НИЙ SAAALEСкидка 50% на виртуальный хостинг и VDS
до 30.11.2025 Подробнее
Выберите продукт

ModSecurity 3 + OWASP CRS в Nginx: установка, динамический модуль, настройка и борьба с false positives

Пошаговая интеграция ModSecurity 3 (libmodsecurity) и OWASP CRS с Nginx. Разберём установку как динамического модуля, безопасное включение правил, настройку порогов и Paranoia Level, аудит-лог, исключения, снижение false positives и рекомендации по производительности.
ModSecurity 3 + OWASP CRS в Nginx: установка, динамический модуль, настройка и борьба с false positives

Если вы хотите получить реальную защиту на периметре веб-приложения и при этом сохранить контроль и предсказуемость, связка Nginx + ModSecurity 3 (libmodsecurity) + OWASP Core Rule Set — проверенный временем выбор. В этой статье соберу практические шаги для админов и девопсов: как аккуратно внедрить WAF через динамический модуль Nginx, включить OWASP CRS, запустить в режиме обнаружения, отловить и погасить false positives, а затем перевести в блокирующий режим. Параллельно разберём тонкости производительности, лимиты тела запроса, исключения (exclusions) и аудит-лог.

Что такое ModSecurity 3 и OWASP CRS в контексте Nginx

ModSecurity 3 — это библиотека libmodsecurity и коннектор-модуль к Nginx. В отличие от старых сборок ModSecurity 2, здесь Nginx взаимодействует с libmodsecurity через отдельный dynamic module. Правила берём из OWASP Core Rule Set (OWASP CRS) — открытого набора сигнатур и эвристик для классических инъекций, XSS, RCE, протокольных аномалий и многого другого.

OWASP CRS работает в режиме anomaly scoring: вместо немедленной блокировки каждое подозрительное совпадение начисляет «штрафные баллы»; при превышении порога запрос блокируется. Это снижает ложные срабатывания и делает настройку управляемой.

Подготовка окружения и варианты установки

Идеальный для продакшна подход — поставить libmodsecurity3 и OWASP CRS из репозитория дистрибутива, а коннектор к Nginx собрать отдельно как динамический модуль с флагом совместимости --with-compat. Важно, чтобы модуль собирался ровно на тех исходниках Nginx, которые установлены в системе.

Пакеты, которые понадобятся

  • libmodsecurity3 (при необходимости libmodsecurity-dev).
  • Правила OWASP CRS (пакет modsecurity-crs или аналог для вашего дистрибутива).
  • Сборочная среда: компилятор, зависимости и исходники Nginx той же версии.

Подсказка: для Debian/Ubuntu удобно использовать apt source nginx, чтобы гарантировать совпадение версии исходников и собранного бинаря.

Пример для Debian/Ubuntu: сборка динамического модуля

sudo apt update
sudo apt install -y libmodsecurity3 libmodsecurity-dev modsecurity-crs build-essential git devscripts
apt source nginx
cd nginx-*

git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx ../ModSecurity-nginx
./configure --with-compat --add-dynamic-module=../ModSecurity-nginx
make modules

sudo mkdir -p /usr/lib/nginx/modules
sudo cp objs/ngx_http_modsecurity_module.so /usr/lib/nginx/modules/

Далее подключим модуль в конфиге Nginx и настроим ModSecurity с OWASP CRS.

Подключение динамического модуля в Nginx

Добавьте строку load_module в верхний уровень конфигурации Nginx (обычно /etc/nginx/nginx.conf или файл в /etc/nginx/modules-enabled/):

load_module /usr/lib/nginx/modules/ngx_http_modsecurity_module.so;

Проверяем синтаксис и версии:

nginx -t
nginx -V

Базовая конфигурация ModSecurity + OWASP CRS

Создадим каталог для локальной конфигурации и аудит-логов:

sudo mkdir -p /etc/nginx/modsec
sudo mkdir -p /var/log/nginx/modsec
sudo chown -R www-data:www-data /var/log/nginx/modsec

Скопируем базовый конфиг ModSecurity и включим движок:

sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf
# В /etc/nginx/modsec/modsecurity.conf установите:
# SecRuleEngine On

Подготовим отдельный main.conf для подключения ModSecurity и CRS из Nginx:

sudo tee /etc/nginx/modsec/main.conf > /dev/null << 'EOF'
# Подключаем основной конфиг ModSecurity
Include /etc/nginx/modsec/modsecurity.conf

# Режим обнаружения для безопасного старта
SecRuleEngine DetectionOnly

# Аудит-лог
SecAuditEngine RelevantOnly
SecAuditLog /var/log/nginx/modsec/audit.log
SecAuditLogType Serial
SecAuditLogParts ABIJDEFHZ

# Лимиты тела запроса (согласуйте с Nginx)
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyInMemoryLimit 1048576

# Включаем OWASP CRS (пути зависят от дистрибутива)
Include /usr/share/modsecurity-crs/crs-setup.conf
Include /usr/share/modsecurity-crs/rules/*.conf
EOF

Подключим ModSecurity в Nginx, но только для динамики — статике WAF не нужен:

http {
    server {
        listen 80;
        server_name example.com;
        root /var/www/app;

        # Статика: WAF выключен
        location ~* \.(?:css|js|png|jpg|jpeg|gif|svg|ico|woff2?)$ {
            access_log off;
            expires 7d;
            add_header Cache-Control "public";
        }

        # API и динамика: WAF включён
        location / {
            modsecurity on;
            modsecurity_rules_file /etc/nginx/modsec/main.conf;
            proxy_pass http://127.0.0.1:9000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

Проверяем конфигурацию и перезапускаем Nginx:

nginx -t
sudo systemctl reload nginx

Диаграмма anomaly scoring OWASP CRS с порогами и срабатываниями правил

Запуск в режиме обнаружения и контроль ложных срабатываний

Начинать стоит с SecRuleEngine DetectionOnly. В этом режиме запросы не блокируются, но ModSecurity и OWASP CRS записывают срабатывания в аудит-лог. Пронаблюдайте хотя бы несколько рабочих дней, соберите список повторяющихся ложных срабатываний и только после этого переходите к блокировкам.

Где смотреть логи:

  • /var/log/nginx/error.log — краткие заметки о блокировках и ошибках.
  • /var/log/nginx/modsec/audit.log — подробный аудит (ID правил, фазы, целевые параметры).

Совет: добавьте в access_log корреляционный идентификатор запроса и прокидывайте его в upstream — это ускорит разбор инцидентов и поиск по аудит-логу.

http {
    log_format main '$remote_addr - $request_id [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';
    access_log /var/log/nginx/access.log main;
    map $request_id $x_req_id { default $request_id; }
    add_header X-Request-ID $x_req_id;
}

Подстройка OWASP CRS: Paranoia Level, пороги и профили

Откройте crs-setup.conf и задайте параметры под свой трафик. Ключевые пункты:

  • Paranoia Level (tx.paranoia_level): 1 — щадящий, 4 — строгий. Для старта берите 1.
  • Пороги блокировки (tx.inbound_anomaly_score_threshold, tx.outbound_anomaly_score_threshold): дефолт 5 — хорошая база.
  • Разрешённые методы (tx.allowed_methods) и типы контента (tx.allowed_request_content_type): сузьте под ваш API.
# Вариант настройки через SecAction одной строкой
SecAction "id:900110,phase:1,pass,nolog,setvar:tx.paranoia_level=1,setvar:tx.inbound_anomaly_score_threshold=5,setvar:tx.outbound_anomaly_score_threshold=4,setvar:tx.allowed_methods=GET HEAD POST PUT PATCH DELETE,setvar:tx.allowed_request_content_type=application/json|application/x-www-form-urlencoded|multipart/form-data"

Повышайте paranoia level и/или снижайте пороги, только если поток ложных срабатываний контролируем. Если false positives много — начните с исключений (ниже), а затем корректируйте уровень.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Исключения: точечные, безопасные, воспроизводимые

Главная ошибка внедрения WAF — массовые отключения правил. Вместо этого применяйте точечные исключения по параметрам, путям или типам контента. В Nginx это можно делать как в общих файлах правил, так и локально в server/location через modsecurity_rules.

Удаление цели у конкретного правила

Допустим, поле search легитимно содержит SQL-операторы, и беспокоит правило из семейства 9421xx (SQLi). Уберём это поле из целей конкретного правила:

modsecurity on;
modsecurity_rules '
  SecRuleEngine On
  SecRuleUpdateTargetById 942100 "!ARGS:search"
';
modsecurity_rules_file /etc/nginx/modsec/main.conf;

Отключение правила на маршруте

Нужен «коридор безопасности» для конкретного endpoint? Локально отключите правило или группу ID:

location = /webhook/incoming {
    modsecurity on;
    modsecurity_rules '
      SecRuleEngine On
      SecRuleRemoveById 932100 932105
    ';
    modsecurity_rules_file /etc/nginx/modsec/main.conf;
    proxy_pass http://127.0.0.1:9000;
}

Практические замечания:

  • Перед исключением убедитесь, что оно действительно нужно: проверьте соответствующие записи в audit.log.
  • Фиксируйте номер задачи в комментариях — пригодится при аудитах.
  • Регулярно пересматривайте список исключений и убирайте устаревшие.

Лимиты тела запроса: согласование Nginx и ModSecurity

Загрузки файлов и крупные JSON часто «ломаются» из‑за несовпадения лимитов. Синхронизируйте client_max_body_size в Nginx и SecRequestBodyLimit в ModSecurity.

server {
    client_max_body_size 12m;

    location /upload {
        modsecurity on;
        modsecurity_rules_file /etc/nginx/modsec/main.conf;
        proxy_request_buffering on;
        proxy_pass http://127.0.0.1:9000;
    }
}

Если client_max_body_size меньше — клиент получит 413 от Nginx; если меньше SecRequestBodyLimit — ModSecurity может вернуть 403 и запись REQBODY_PROCESSOR_ERROR в аудит-лог. Проверяйте на реальных нагрузках.

Согласование лимитов тела запроса между Nginx и ModSecurity

Перевод в блокирующий режим

Когда поток ложных срабатываний под контролем и исключения согласованы, меняем SecRuleEngine DetectionOnly на SecRuleEngine On в /etc/nginx/modsec/main.conf, перезагружаем Nginx и продолжаем мониторинг.

  • Включайте блокировку поэтапно: с одного сервера или части маршрутов.
  • Оценивайте метрики отказов, error budget и корреляцию с релизами приложения.
  • Постепенно расширяйте покрытие.

Производительность и зона применения WAF

ModSecurity 3 добавляет задержку на обработку запроса (обычно миллисекунды; зависит от набора правил и тела). Чтобы не «жечь» ресурсы:

  • Не включайте WAF для статики и медиа.
  • Исключайте health-check-и и служебные локации.
  • Для крупных загрузок включайте буферизацию запросов (proxy_request_buffering on) и синхронизируйте лимиты.
  • Подбирайте разумный paranoia level и пороги; избегайте избыточных кастомных правил.

Планируйте ресурсы. На нагруженных API выносите проверяемые маршруты в отдельные серверные блоки или инстансы. Если нужна изоляция и гибкое масштабирование, разверните WAF на отдельном VDS.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Логирование и аудит: что включить

Для продуктивного расследования инцидентов обеспечьте:

  • Access-log с $request_id и ключевыми полями клиента.
  • Audit-log ModSecurity с частями ABIJDEFHZ — достаточно контекста без избыточности.
  • Error-log Nginx уровня info или notice на этапе отладки.

Практики для audit-log:

  • Храните логи отдельно, включите ротацию и убедитесь, что она не ломает дескрипторы (совместите с перезагрузкой Nginx).
  • Рассмотрите JSON-формат — удобно для парсинга и передачи в SIEM/лог-агрегатор.

Тестирование правил: быстро проверить срабатывание

Чтобы убедиться, что WAF работает, отправьте очевидный «атакующий» паттерн, например строку, похожую на SQLi или XSS:

curl -i 'http://example.com/?q=1%20UNION%20SELECT%201,2,3'

В аудит-логе вы увидите срабатывание правил семейства 9421xx. В режиме обнаружения будет запись, а в блокирующем — ответ с кодом 403.

Типичные ошибки и их диагностика

  • unknown directive "modsecurity": модуль не загружен или неверный путь в load_module.
  • Версия Nginx не совпадает: модуль собран не с теми исходниками — пересоберите с apt source nginx.
  • Аудит-лог пуст: проверьте SecAuditEngine, права на каталог логов и ротацию.
  • Много 403 на загрузках: проверьте client_max_body_size, SecRequestBodyLimit и proxy_request_buffering.
  • False positives на JSON: сузьте tx.allowed_request_content_type и добавьте точечные SecRuleUpdateTargetById для «шумных» полей.

Стратегия внедрения: от «детекта» к «блокировке» без аварий

  1. Включите WAF на ключевых динамических маршрутах в режиме DetectionOnly.
  2. Соберите статистику по срабатываниям и «шумным» параметрам.
  3. Внедрите точечные исключения и профиль CRS (paranoia, пороги, методы, типы контента).
  4. Включите блокировку на ограниченном сегменте и оцените отказоустойчивость.
  5. Расширяйте покрытие, обновляйте правила, проводите «гигиену» исключений.

Поддержка и обновления

Регулярно обновляйте:

  • libmodsecurity3 — исправления стабильности и безопасности;
  • OWASP CRS — новые правила и уточнения паттернов;
  • коннектор-модуль — при обновлении Nginx пересобирайте модуль на соответствующих исходниках.

Перед обновлением правил включайте «детект-режим» на тестовом стенде или канареечном сервере, чтобы поймать возможные новые false positives до выката на весь прод. И не забывайте про HTTPS: корректная TLS-терминация и актуальные SSL-сертификаты — обязательная база для безопасного периметра.

Вывод

Связка Nginx + ModSecurity 3 + OWASP CRS — зрелый WAF, который можно внедрить без боли, если идти по «лестнице зрелости»: динамический модуль с совместимостью, корректное подключение CRS, старт в режиме обнаружения, точечные исключения и постоянный мониторинг. Двигайтесь итерациями, фиксируйте эффекты на метриках — и WAF станет надёжным и предсказуемым слоем защиты вашего веб-приложения.

Поделиться статьей

Вам будет интересно

CDC в PostgreSQL с Debezium: logical decoding, Kafka/Redpanda и outbox OpenAI Статья написана AI (GPT 5)

CDC в PostgreSQL с Debezium: logical decoding, Kafka/Redpanda и outbox

Разбираем, как включить logical decoding, настроить replication slots, выбрать pgoutput или wal2json и подключить Debezium к Kafka ...
cert-manager в Kubernetes: Issuer, ClusterIssuer и DNS-01 на практике OpenAI Статья написана AI (GPT 5)

cert-manager в Kubernetes: Issuer, ClusterIssuer и DNS-01 на практике

Подробный разбор автоматизации TLS в Kubernetes с cert-manager: когда выбирать Issuer или ClusterIssuer, как настроить ACME DNS-01 ...
Redis replication практикум: PSYNC2, diskless, failover и измеримый RPO OpenAI Статья написана AI (GPT 5)

Redis replication практикум: PSYNC2, diskless, failover и измеримый RPO

Разбираем практический план настройки и измерений: как работает PSYNC2 и репликационный backlog, чем полезна бездисковая репликаци ...