Задача пришла в формулировке, знакомой многим: «Wazuh работает, но сигналов столько, что не разобрать, где ложные срабатывания, а где реальные атаки. Надо что-то с этим сделать».

Для контекста: Wazuh – это open-source SIEM, который собирает логи, детектирует подозрительную активность и умеет на неё реагировать. Инструмент хороший, но дефолтный набор правил – как швейцарский нож: вроде и режет, и открывает, а под конкретную задачу всё равно приходится подтачивать. Он рассчитан на «среднюю» инфраструктуру и без адаптации генерирует много шума.

Моя задача сводилась к тому, чтобы отделить этот шум от значимых событий, не потеряв при этом сами атаки. Ниже – методология и грабли, на которые я наступил. Будет полезно тем, кто настраивает Wazuh впервые, и тем, кто хочет разгрузить аналитиков от потока ложных тревог.

Знакомство с правилами

Дефолтные правила Wazuh лежат в /var/ossec/ruleset/rules/ – тысячи строк XML. Да, XML в 2026 году. Формат многословный (готовьтесь к закрывающим тегам в промышленных количествах), но к нему быстро привыкаешь, а главное – менять эти файлы напрямую не нужно.

Все локальные правки выносятся в local_rules.xml и в дополнительно загружаемые файлы. Удобнее работать через веб-интерфейс: он проверяет структуру XML на лету (парные теги, корректность вложенности) и не даст случайно сломать рабочую конфигурацию – наломать дров можно только в своей «песочнице».

Типовые ложные срабатывания

Чаще всего нас будили три сценария:

  1. SSH-брутфорс с localhost. Ansible выполняет ssh localhost в ходе provisioning, а Wazuh уверенно трактует это как попытку перебора. Кажется, что атака, а на деле штатный провижининг.

  2. curl на самого себя. Healthcheck'и мониторинга обращаются к эндпоинтам раз в 30 секунд – для правила это выглядит как подозрительная HTTP-активность. На практике это просто Prometheus занимается своим делом.

  3. Изменения файлов в /tmp. CI/CD оставляет там артефакты вроде wget-log.42, а FIM-модуль реагирует на каждое изменение как на потенциальную компрометацию – и тревожит дежурного инженера в три ночи ради лога wget.

Все три – классический фоновый шум, который маскирует реальные инциденты.

Как пишутся локальные правила

Минимальное правило выглядит так:

<group name="ssh">
  <rule id="100002" level="0">
    <if_group>ssh</if_group>
    <match>127.0.0.1|localhost</match>
    <description>SSH с localhost — провижининг Ansible, не атака</description>
  </rule>
</group>

Разберём по элементам:

  • id — уникальный номер правила. Диапазон 100000+ зарезервирован под локальные правила, так что коллизий с дефолтными не будет – можно не стесняться.

  • level — уровень критичности от 0 до 16. level="0" полностью подавляет алерт, высокие значения эскалируют событие (15 – это уже «будите дежурного»).

  • if_group — группа правил, к которой привязывается логика.

  • match — шаблон поиска по содержимому лога.

  • description — текст, который увидит дежурный аналитик. Здесь стоит писать по делу и понятно: не «SSH auth from loopback», а явное указание, что это за событие и почему оно безопасно. В три часа ночи коллега скажет спасибо.

Оптимизация и профилирование

После первого набора правил имеет смысл замерить, как изменилась нагрузка и не появились ли побочные эффекты.

wazuh-logtest

Основной инструмент отладки – утилита wazuh-logtest. Она принимает строку лога и показывает, какое правило сработало, с каким уровнем и по какой причине:

# wazuh-logtest
2026 May 15 10:42:00 sshd[12345]: Failed password for root from 127.0.0.1 port 22 ssh2

С ней процесс настройки правил становится гораздо предсказуемей. По сути это try/catch: прогнал лог, увидел результат, поправил.

Что дало наибольший эффект:

  1. Замена regex на match там, где это возможно

    Регулярные выражения красивы, но дороги по производительности. На больших объёмах логов простое сопоставление по подстроке заметно экономит ресурсы.

  2. Корректная настройка frequency и timeframe

    frequency задаёт число срабатываний за timeframe секунд. Стандартный порог детекта брутфорса – 10 попыток за 60 секунд – не подходит для localhost, где Ansible легко генерирует сотню обращений за десяток секунд. Порог пришлось пересмотреть, а для localhost вынести отдельное правило-исключение.

  3. Правила-исключения через if_sid

    Вместо переписывания дефолтного правила добавляется исключение, которое подавляет срабатывание в конкретном случае:

    <rule id="100003" level="0">
    <if_sid>5710</if_sid>
    <match>127.0.0.1</match>
    <description>Исключаем localhost из детекта брутфорса</description>
    </rule>
  4. Группировка правил. Локальные правки логично разнести по группам (sshd, fim, apache), а не размазывать по конфигу. Это упрощает поддержку и аудит – и вам, и тем, кто полезет в конфиг после вас.

Грабли, на которые стоит обратить внимание

Один показательный случай. Я написал правило, детектирующее wget к определённому URL. Через неделю аналитик сообщил о срабатывании каждые пять минут – оказалось, под правило попадал наш собственный мониторинг, скачивающий обновления. Решилось добавлением if_sid на событие мониторинга.

Так что прежде чем включать правило в продакшен, убедитесь, что не станете его первой жертвой сами. Здесь снова выручает wazuh-logtest – прогон реальных логов до выкатки экономит много времени и нервов.

Результат. После настройки поток ложных алертов снизился до уровня, при котором аналитики перестали их игнорировать. А значимые события – например, реальные попытки доступа – стали заметны на чистом фоне. Один из коллег прокомментировал это так: «Я впервые за месяц увидел реальную атаку, а не Ansible».

Выводы

  1. Писать правила несложно – сложно не навредить. Каждый level="0" потенциально скрывает атаку, а неаккуратный match способен отсечь важное событие. Любое подавляющее правило стоит проверять на боевых логах.

  2. Исключения важнее переопределений. Не переписывайте дефолтные правила – добавляйте исключения поверх них. По сути это паттерн Decorator: расширяем поведение, не меняя исходное.

  3. Документируйте описания. description читают дежурные аналитики, в том числе ночью. Понятная формулировка ускоряет разбор и снижает число эскалаций.

  4. XML не страшен. Формат многословный, но предсказуемый и вполне рабочий, если соблюдать структуру и держать правки в отдельных файлах.

Грамотно настроенный Wazuh из источника шума превращается в рабочий инструмент мониторинга. Главное – относиться к набору правил как к живой конфигурации: её нужно поддерживать и пересматривать по мере того, как меняется инфраструктура.

Описанная история – про то, сколько ресурсов уходит, чтобы мониторинг приносил пользу, а не будил инженера среди ночи из-за wget-log.42. Настройка правил, отсев ложных срабатываний, разбор логов и реакция на инциденты требуют рук и экспертизы, которых у небольшой команды часто не хватает.

Эту нагрузку можно делегировать. Cloud4Y предоставляет мониторинг в администрировании: анализ логов, умные оповещения с уведомлениями в Telegram и единая панель, где видны метрики и узкие места инфраструктуры. Алерты настраиваются только по значимым событиям. Тонкую настройку и развёртывание берут на себя инженеры провайдера.

А для новых клиентов с Хабра действует скидка 20% по промокоду HABR20 на услуги Cloud4Y, подробности на странице акции.

Комментарии (1)


  1. Granulex
    09.06.2026 08:14

    local_rules.xml – правильный слой для исключений. Есть более ранний и эффективный уровень: ossec.conf на самих агентах. События, отфильтрованные там, не достигают менеджера вообще – ни трафик, ни CPU на парсинг. Wazuh часто начинают тюнить с правил, тогда как дефолтные настройки syscheck мониторят /tmp, /dev и всё подряд. Половину шума можно убрать ещё до написания первого XML-правила.