ModSecurity — это модуль веб-сервера, который проверяет каждый HTTP-запрос и ответ по набору правил и умеет блокировать атаку раньше, чем она дойдёт до приложения. Сам по себе модуль лишь исполнитель: содержание в него вкладывает набор правил OWASP Core Rule Set (CRS), где собраны сигнатуры SQL-инъекций, XSS, path traversal, внедрения команд и другой типовой активности. Ниже — рабочая связка ModSecurity 3 и CRS для nginx на Debian или Ubuntu: установка, проверка, настройка исключений и честный разговор об ограничениях.

Что WAF даёт и чего не даёт

WAF закрывает класс атак, которые трудно отловить на уровне приложения: массовые сканеры, известные уязвимости в зависимостях, грубые попытки инъекций. Он не заменяет исправленный код, серверную валидацию и обновления библиотек. Практическая польза появляется, когда защита стоит перед конкретным сайтом и её журнал кто-то регулярно читает.

  • фильтрация запросов и ответов по сигнатурам CRS;
  • журнал срабатываний с идентификаторами правил;
  • режим наблюдения, когда блокировка ещё не включена;
  • точечные исключения для легитимных форм и API.

Установка ModSecurity для nginx

В Debian и Ubuntu модуль есть в готовом пакете, сборка из исходников не требуется. Заодно проверьте, что nginx видит динамический модуль и конфигурация остаётся валидной.

sudo apt update
sudo apt install nginx libnginx-mod-http-modsecurity
ls /etc/nginx/modules-enabled/
nginx -t

Пакет добавляет файл подключения в modules-enabled, а сам модуль лежит в /usr/lib/nginx/modules. Для Apache логика похожая: пакет libapache2-mod-security2 и команда a2enmod security2. Дальше примеры для nginx, потому что он чаще стоит перед приложением.

Подключаем OWASP CRS

Правила удобно держать в /etc/nginx/modsec. Клонируйте репозиторий и создайте рабочий конфиг из шаблона.

sudo mkdir -p /etc/nginx/modsec
sudo git clone https://github.com/coreruleset/coreruleset.git /etc/nginx/modsec/coreruleset
cd /etc/nginx/modsec/coreruleset
sudo cp crs-setup.conf.example crs-setup.conf
sudo install -d -o www-data -g www-data /var/lib/modsecurity
sudo install -o www-data -g adm -m 640 /dev/null /var/log/nginx/modsec_audit.log
sudo touch /etc/nginx/modsec/local-exclusions.conf

Теперь опишите базовые параметры движка. Файл modsecurity.conf создаём сами, чтобы не зависеть от того, какие образцы конфигов положил дистрибутив.

SecRuleEngine DetectionOnly
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html application/json
SecResponseBodyLimit 1048576
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLog /var/log/nginx/modsec_audit.log
SecTmpDir /var/lib/modsecurity
SecDataDir /var/lib/modsecurity

Осталось связать всё в main.conf. Порядок включений важен: сначала настройки движка, затем crs-setup.conf, затем сами правила и локальные исключения.

Include /etc/nginx/modsec/modsecurity.conf
Include /etc/nginx/modsec/coreruleset/crs-setup.conf
Include /etc/nginx/modsec/coreruleset/rules/*.conf
Include /etc/nginx/modsec/local-exclusions.conf

В блоке server включите модуль и укажите файл правил:

server {
    listen 443 ssl;
    server_name example.ru;

    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsec/main.conf;
}

Файл local-exclusions.conf уже создан пустым, он понадобится позже. Проверка конфигурации и перезагрузка:

sudo nginx -t && sudo systemctl reload nginx

Проверка в режиме DetectionOnly

Первый запуск всегда делайте без блокировки. Убедитесь, что обычный запрос проходит, а тестовая инъекция фиксируется в журнале.

curl -s -o /dev/null -w '%{http_code}\n' 'https://example.ru/?q=hello'
curl -s -o /dev/null -w '%{http_code}\n' 'https://example.ru/?id=1%27%20OR%20%271%27%3D%271'
sudo tail -n 30 /var/log/nginx/modsec_audit.log

В режиме DetectionOnly оба запроса вернут 200, но во втором в журнале появится запись с id правила, например 942100 для SQL-инъекции. Если журнал пуст, проверьте права на каталоги и убедитесь, что модуль действительно загружен.

Включаем блокировку и настраиваем уровень

После недели наблюдения можно переключить движок в боевой режим. Не начинайте сразу с максимальной паранойи: CRS имеет уровни с первого по четвёртый, и на высоких уровнях заметно растёт число ложных срабатываний.

sudo sed -i 's/^SecRuleEngine .*/SecRuleEngine On/' /etc/nginx/modsec/modsecurity.conf
sudo nginx -t && sudo systemctl reload nginx
curl -s -o /dev/null -w '%{http_code}\n' 'https://example.ru/?id=1%27%20OR%20%271%27%3D%271'

Теперь ожидается 403. Уровень задаётся правилом 900000 в crs-setup.conf, менять значение нужно именно там, до загрузки остальных правил. Начните с первого уровня и повышайте только после разбора журналов.

Исключения без отключения защиты

Легитимная форма может содержать текст, похожий на атаку. Не отключайте правило целиком — уберите из проверки конкретный параметр. Исключения складывайте в local-exclusions.conf, который подключается после CRS.

# не проверять поле message правилом 942100
SecRuleUpdateTargetById 942100 "!ARGS:message"

# отключить правило для конкретного пути API
SecRule REQUEST_URI "@beginsWith /api/v1/feedback" \
  "id:1001,phase:1,pass,nolog,ctl:ruleRemoveTargetById=942100;ARGS:message"

После правки снова nginx -t и reload. Каждое исключение фиксируйте комментарием с датой и причиной, иначе через полгода никто не вспомнит, зачем оно нужно.

Диагностика и производительность

Сводка по срабатываниям помогает найти самые шумные правила:

sudo grep -o 'id "[0-9]*"' /var/log/nginx/modsec_audit.log | sort | uniq -c | sort -rn | head
sudo grep -c 'id "949110"' /var/log/nginx/modsec_audit.log

Правило 949110 означает превышение порога аномалий на входящем трафике. Проверка тел ответов и больших файлов стоит процессорного времени, поэтому статику и скачивания лучше вывести из-под анализа:

SecRule REQUEST_URI "@rx ^/(static|media|download)/" \
  "id:1000,phase:1,pass,nolog,ctl:ruleEngine=Off"

На слабой машине включайте SecResponseBodyAccess только для API с JSON. Замеряйте задержку до и после: разница в единицы миллисекунд нормальна, рост в разы — повод пересмотреть правила.

Отдельно настройте ротацию журнала: при активном сайте файл растёт быстро, а разбор гигабайтного лога превращается в отдельную задачу. В logrotate укажите daily, rotate 14 и postrotate с reload nginx, чтобы дескриптор переоткрылся корректно. Для отладки включайте SecDebugLog только на время: подробный вывод заметно замедляет обработку запросов.

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

Чек-лист перед боевым режимом

  • неделя логов в DetectionOnly и разбор всех срабатываний;
  • исключения оформлены отдельным файлом с комментариями;
  • настроена ротация modsec_audit.log через logrotate;
  • проверены формы входа, загрузка файлов и админка;
  • есть тест, подтверждающий блокировку и пропуск обычного запроса.

Итог

ModSecurity с OWASP CRS — быстрый способ добавить сайту слой защиты от типовых атак без переписывания кода. Начните с DetectionOnly, соберите статистику, настройте точечные исключения и только потом включайте блокировку. Помните, что ModSecurity 3 развивается неспешно, а CRS требует регулярного обновления правил; альтернативой стоит держать в поле зрения Coraza. WAF дополняет, но не отменяет обновления зависимостей и нормальную валидацию входных данных.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте