Привет, хабровчане! Если вы занимаетесь DevOps, системным администрированием или кибербезопасностью, то Wazuh — это ваш must-have для мониторинга и SIEM. В этой статье (и соответствующем видео на моём канале) мы разберём секцию в конфигурации агента Wazuh. Это ключевой компонент Logcollector'а, который отвечает за сбор логов из файлов, системных событий, команд и даже journald. Без правильной настройки вы рискуете пропустить важные события или утонуть в шуме.
Статья основана на официальной документации, с практическими примерами из реальных конфигов. Если необходимо видео, то можно посмотреть тут.
Location: Откуда брать логи?
<location> — это основа любого <localfile>. Без неё сбор не запустится. Указывает путь к файлу, канал событий Windows, macOS ULS или journald.
Зачем? Определяет источник для анализа. Когда применять? Всегда. Для статичных файлов — прямой путь; для ротации — strftime (%Y-%m-%d) или wildcard (*). Максимум 1000 файлов на мониторинг. Wildcard не сочетается со strftime.
Примеры из конфига (agent.conf):
<!-- Windows event channels -->
<localfile>
<location>Microsoft-Windows-Sysmon/Operational</location>
<log_format>eventchannel</log_format>
</localfile>
<localfile>
<location>Microsoft-Windows-Windows Firewall With Advanced Security/Firewall</location>
<log_format>eventchannel</log_format>
</localfile>
<!-- Wildcard на Windows/Linux -->
<localfile>
<location>C:\xampp\apache\logs\*.log</location>
<log_format>syslog</log_format>
</localfile>
<localfile>
<location>C:\logs\file-%Y-%m-%d.log</location>
<log_format>syslog</log_format>
</localfile>
<!-- JSON-логи приложений -->
<localfile>
<location>/var/log/vault/audit_vaut.json</location>
<log_format>json</log_format>
</localfile>
<localfile>
<location>/var/log/fortigate/audit.log</location>
<log_format>syslog</log_format>
</localfile>
Command, Alias и Frequency: Мониторинг динамики
<command> — выполняет команду и читает вывод как лог (одна строка) или <full_command> (многострочный).
Зачем? Для метрик без файлов (df, netstat).
Когда? С <frequency> для периодических чеков (default: 360 сек). Требует logcollector.remote_commands=1 в /var/ossec/etc/local_internal_options.conf на агенте
<alias> — заменяет имя команды в алертах для читаемости. <frequency> — интервал в секундах.
Примеры:
<!-- Проверка IP раз в сутки -->
<localfile>
<log_format>command</log_format>
<command>curl -s https://ifconfig.me</command>
<alias>white_ip</alias>
<frequency>86400</frequency>
</localfile>
<!-- Кто залогинен каждые 5 мин -->
<localfile>
<log_format>command</log_format>
<command>w</command>
<alias>logged</alias>
<frequency>300</frequency>
</localfile>
<!-- Full output (многострочный) -->
<localfile>
<log_format>full_command</log_format>
<command>w</command>
<alias>logged</alias>
<frequency>300</frequency>
</localfile>
Only-future-events: Избежать дублей
Зачем? Читает только новые логи после рестарта (default: yes).
Когда? Для efficiency; no — для полного бэклога.
Атрибут max-size: Пропускает старые > указанного (e.g., 10MB).
Примеры:
<localfile>
<location>/var/log/vault/audit_vaut.json</location>
<log_format>json</log_format>
<only-future-events max-size="1GB">yes</only-future-events>
</localfile>
<localfile>
<location>/var/log/fortigate/audit.log</location>
<log_format>syslog</log_format>
<only-future-events>no</only-future-events>
</localfile>
Query: Селективный сбор
Зачем? Фильтр для eventchannel (XPath) или macOS (predicates).
Когда? Для Windows/macOS, чтобы ловить конкретные ID/процессы.
Примеры:
<!-- Windows: Логины типа 2/10 -->
<localfile>
<location>Security</location>
<log_format>eventchannel</log_format>
<query>Event[System/EventID = 4624 and (EventData/Data[@Name='LogonType'] = 2 or EventData/Data[@Name='LogonType'] = 10)]</query>
</localfile>
<!-- macOS: SSHD debug -->
<localfile>
<location>macos</location>
<log_format>macos</log_format>
<query type="log,trace" level="debug">process == "sshd" OR message CONTAINS "invalid"</query>
</localfile>
Target и Out_format: Кастомизация вывода
<target> — куда слать логи (default: agent). Зачем? Для интеграции с внешним SIEM. <out_format> — форматирует с placeholders (timestamp, hostname, base64_log и др.). Атрибут target: Для конкретного сокета.
log - cообщение из лога, распарсенное согласно <log_format>
json_escaped_log - cообщение из лога с экранированием JSON-символов (например, кавычек, обратных слэшей).
output - то же, что log (алиас, используется для вывода команд, либо для формирования лога).
location - путь к исходному лог-файлу или команда.
command - команда или её алиас, если используется <command> (алиас location).
timestamp - текущий таймстэмп (в момент отправки лога) в формате RFC3164 (например, Sep 20 23:25:00).
timestamp <FORMAT> - пользовательский таймстэмп в формате strftime (например, $(timestamp %Y-%m-%d %H:%M:%S) → 2025-09-20 23:25:00).
hostname - имя хоста системы.
host_ip - основной IP-адрес хоста.
Примеры:
<localfile>
<location>/var/log/secure</location>
<log_format>syslog</log_format>
<out_format>Original event: $(log)</out_format>
</localfile>
<localfile>
<location>/var/log/app.json</location>
<log_format>json</log_format>
<out_format>{ "time": "$(timestamp %Y-%m-%d %H:%M:%S)", "log": "$(json_escaped_log)" }</out_format>
</localfile>
<localfile>
<location>/var/log/secure</location>
<log_format>syslog</log_format>
<out_format>BASE64: $(base64_log)</out_format>
</localfile>
<localfile>
<log_format>command</log_format>
<command>echo "Test output from 2025-10-23"</command>
<out_format>Command result: $(output)</out_format>
</localfile>
<localfile>
<location>/var/log/secure</location>
<log_format>syslog</log_format>
<out_format>From file: $(location) — $(log)</out_format>
</localfile>
<localfile>
<command>df -h</command>
<alias>disk-check</alias>
<log_format>command</log_format>
<out_format>Via command: $(command) — $(log)</out_format>
</localfile>
<localfile>
<location>/var/log/secure</location>
<log_format>syslog</log_format>
<out_format>Sent at: $(timestamp) — $(log)</out_format>
</localfile>
<localfile>
<location>/var/log/secure</location>
<log_format>syslog</log_format>
<out_format>Sent at: $(timestamp %Y-%m-%dT%H:%M:%SZ) — $(log)</out_format>
</localfile>
<localfile>
<location>/var/log/secure</location>
<log_format>syslog</log_format>
<out_format>Host: $(hostname) reports: $(log)</out_format>
</localfile>
<localfile>
<location>/var/log/secure</location>
<log_format>syslog</log_format>
<out_format>IP: $(host_ip) — $(log)</out_format>
</localfile>
<ignore_binaries> Игнорирует бинарники (UTF-8/ASCII check).
<localfile>
<log_format>syslog</log_format>
<location>/var/logs/*</location>
<ignore_binaries>yes</ignore_binaries>
</localfile>
Log_format: Парсинг по шаблонам
Критично: определяет, как читать лог. Влияет на декодеры и алерты. Виды форматов:
syslog - Для текстовых логов в формате syslog (например, timestamp hostname process: message).
json - для логов, где каждая строка — валидный JSON-объект.
snort-full - для полного формата логов Snort (IDS/IPS).
squid - для логов прокси-сервера Squid.
eventlog - для старого формата Windows Event Log (до Vista).
eventchannel - для современных Windows Event Logs (Vista и новее) в JSON-формате.
macos - для macOS Unified Logging System (ULS), в формате syslog. Требует <location>macos</location> и <query>.
journald - для логов systemd journal, в формате syslog.
audit - для логов Linux Auditd. Объединяет последовательные логи с одинаковым ID в одно событие.
mysql_log - Для логов MySQL (не поддерживает многострочные логи). (проще использовать через syslog)
postgresql_log - для логов PostgreSQL (не поддерживает многострочные логи). (проще использовать через syslog)
nmapg - для логов Nmap в grep-формате. (проше доработать скрипт по сканированию, и вывод формировать в json формате)
iis - для логов IIS (Windows Web Server).
djb-multilog - для логов в формате Daemontools (DJB).
multi-line-regex - для приложений с переменным числом строк на событие. Требует <multiline_regex>.
multi-line - используется для мониторинга приложений, где каждое событие записывается в лог в виде фиксированного числа строк (например, 3 строки на событие). Требуется указать количество строк в формате multi-line: NUMBER. Wazuh объединяет эти строки в одно событие, даже если в них содержатся разные таймстэмпы, что позволяет сохранить полный контекст события для анализа.
<localfile>
<location>/var/log/syslog</location>
<log_format>syslog</log_format>
</localfile>
<localfile>
<location>/var/log/app.json</location>
<log_format>json</log_format>
</localfile>
<localfile>
<location>/var/log/snort/alert</location>
<log_format>snort-full</log_format>
</localfile>
<localfile>
<location>/var/log/squid/access.log</location>
<log_format>squid</log_format>
</localfile>
<localfile>
<location>Application</location>
<log_format>eventlog</log_format>
</localfile>
<localfile>
<location>Security</location>
<log_format>eventchannel</log_format>
</localfile>
<localfile>
<location>macos</location>
<log_format>macos</log_format>
<query type="log,trace" level="debug">process == "sshd"</query>
</localfile>
<localfile>
<location>journald</location>
<log_format>journald</log_format>
</localfile>
<localfile>
<location>/var/log/audit/audit.log</location>
<log_format>audit</log_format>
</localfile>
<localfile>
<location>C:\inetpub\logs\LogFiles\W3SVC1\u_ex%y%m%d.log</location>
<log_format>iis</log_format>
</localfile>
<localfile>
<location>/var/log/mysql/mysql.log</location>
<log_format>mysql_log</log_format>
</localfile>
<localfile>
<location>/var/log/postgresql/postgresql-16-main.log</location>
<log_format>postgresql_log</log_format>
</localfile>
<localfile>
<location>/var/log/nmap.log</location>
<log_format>nmapg</log_format>
</localfile>
<localfile>
<location>/var/log/app.log</location>
<log_format>multi-line: 3</log_format>
</localfile>
<localfile>
<location>/var/log/my_python_app.log</location>
<log_format>multi-line-regex</log_format>
<multiline_regex replace="wspace">^Traceback</multiline_regex>
</localfile>
Фильтры: Age, Exclude, Reconnect_time
<age> Только свежие файлы (>1d игнор).
<localfile>
<log_format>syslog</log_format>
<location>/var/logs/*</location>
<age>1d</age>
</localfile>
<exclude> Исключить по wildcard.
<localfile>
<location>/var/log/*</location>
<log_format>syslog</log_format>
<exclude>/var/log/e*</exclude>
</localfile>
<reconnect_time> Переподключение для eventchannel (default: 5s).
<localfile>
<location>Security</location>
<log_format>eventchannel</log_format>
<reconnect_time>10s</reconnect_time>
</localfile>
Ignore и Restrict: Точная фильтрация
<ignore> Исключить по regex (PCRE2/osregex/osmatch; OR-логика).
<localfile>
<location>/var/log/audit/audit.log</location>
<log_format>audit</log_format>
<ignore type="PCRE2">type=.+_CHANGE</ignore>
</localfile>
<localfile>
<location>/var/log/audit/audit.log</location>
<log_format>audit</log_format>
<ignore type="PCRE2">type=.+_CHANGE</ignore>
<ignore type="osregex">type=CONFIG_\.+</ignore>
<ignore type="osmatch">DEBUG</ignore>
</localfile>
<restrict> Обработать только по regex (AND; приоритет ignore). Не для eventchannel.
<localfile>
<location>/custom/file/path</location>
<log_format>syslog</log_format>
<restrict type="PCRE2">username_\d?</restrict>
</localfile>
<localfile>
<location>/custom/file/path</location>
<log_format>syslog</log_format>
<restrict type="PCRE2">username_\d?</restrict>
<restrict type="osregex">Jun\.+</restrict>
<ignore type="osmatch">DEBUG</ignore>
</localfile>
Filter: Для journald
Зачем? Фильтр по полям (PCRE2; AND в блоке, OR между блоками).
<localfile>
<location>journald</location>
<log_format>journald</log_format>
<filter field="_SYSTEMD_UNIT">^ssh.service$</filter>
</localfile>
<localfile>
<location>journald</location>
<log_format>journald</log_format>
<filter field="_SYSTEMD_UNIT">^cron.service$</filter>
<filter field="PRIORITY" ignore_if_missing="yes">[0-3]</filter>
</localfile>
Итог: Масштабируйте Wazuh умно
<localfile> — это 80% успеха в сборе данных. Тестируйте на dev, мониторьте /var/ossec/logs/ossec.log на ошибки, комбинируйте с группами агентов. В Wazuh 4.7+ акцент на journald и regex — идеально для микросервисов.