О чем материал
Изучаем внутреннее устройство компонентов Linux, участвующих в маршрутизации системных журналов
Я периодически сталкиваюсь с вопросами клиентов и коллег из смежных отделов о том, как можно оптимизировать работу разных компонентов журналирования внутри Linux. В основном они касаются предлагаемых нами настроек доставки журналов в MaxPatrol SIEM и того, как их можно модифицировать с оглядкой на особенности конкретной инфраструктуры. Поэтому я составил схему различных вариантов взаимодействия компонентов журналирования Linux между собой для быстрого поиска ответов.
В этой статье я не затрону всех тонкостей, известных лишь узкому кругу специалистов, а кратко опишу каждый блок схемы и тем самым постараюсь ответить на большинство возникающих вопросов. Каждый раздел будет посвящен отдельной группе компонентов, принимающих участие в транспортировке журналов от источника к точке назначения.
Общая схема
На рис. 1 приведена полная схема взаимодействия компонентов журналирования в Linux.

Некоторые участки схемы представляют из себя маршрут доставки событий в MaxPatrol SIEM, настройку которого мы описываем в нашей документации по настройке источников.
Что ж, приступим к разбору схемы. Каждый следующий раздел будет описывать отдельный «регион» этой большой «карты мира».
Компоненты аудита Linux
Скажу прямо, мы солидарны со всеми коллегами из нашей отрасли: встроенный аудит Linux далек от идеала. Но пока мы только ищем грамотную альтернативу, которая была бы сбалансирована по нашим требованиям к функциональности и выглядела надежной, — работаем с тем, что имеем. Все потому, что системные события важны для понимания происходящего на узле. А найти решение, идеально подходящее и нам и всем клиентам, пока что видится довольно внушительной задачей.
Подробнее о содержимом событий аудита, архитектуре и взаимодействии компонентов подсистемы читайте здесь.

Подсистема аудита
Это полноценный компонент ядра Linux, способный регистрировать все выполняющиеся системные вызовы. Со стороны пользовательского пространства общение с ним происходит через специально выделенный netlink-сокет. Используя официальные утилиты в пакете auditd, администратор узла может включать и отключать подсистему, устанавливать для нее правила мониторинга, анализировать статистику и т. п. Различные сторонние утилиты могут использовать API из библиотеки libaudit для формирования событий в формате auditd, которые затем попадают в общий журнал.
Служба аудита
Это компонент на стороне пользовательского пространства, который получает события со стороны ядра. Рассмотрим несколько файлов его конфигурации:
- /etc/audit/auditd.conf — содержит системные параметры службы.
Версии auditd ниже 3.0:
local_events = yes
write_logs = yes
log_file = /var/log/audit/audit.log
log_format = ENRICHED
dispatcher = /sbin/audispd
# ...
Версии auditd, начиная с 3.0:
local_events = yes
write_logs = yes
log_file = /var/log/audit/audit.log
log_format = ENRICHED
plugin_dir = /etc/audit/plugins.d
# ...
Полный список доступных директив можно посмотреть на man-странице auditd.conf(5). В контексте транспортировки журналов нас интересуют только некоторые из них:
- local_events. Необходимо убедиться, что выставлено в yes, чтобы события для текущего узла в принципе генерировались.
- write_logs. Можно установить в yes, чтобы события сохранялись в локальный файл журнала. Мы же рекомендуем выставлять ее в no, так как с предлагаемыми нами параметрами журналы будут сохраняться сразу в общий системный журнал.
- log_file. Полный путь к локальному файлу журнала.
- dispatcher/plugin_dir. Определяют дальнейшее движение событий в сторону диспетчера аудита. Директива plugin_dir в новых версиях auditd пришла из файла конфигурации /etc/audisp/audispd.conf, о котором я расскажу ниже.
Стоит также отметить, что служба auditd имеет встроенный механизм ротации локальных журналов (в наших рекомендациях по настройке мы его не касаемся). Но если вам все-таки понадобится эта функциональность, то вот директивы, которые за нее отвечают:
- max_log_file_action. Необходимо установить в ROTATE для включения ротации по достижении файлом журнала определенного размера. Можно также указать KEEP_LOGS, но тогда директива num_logs будет игнорироваться, что может привести к переполнению хранилища.
- max_log_file. Размер файла журнала в мегабайтах, при достижении которого происходит ротация.
- num_logs. Максимальное количество единовременно хранимых файлов журнала.
Если вам потребуется выполнить ротацию не на основе размера файла, а через заданные промежутки времени, придется проявить фантазию. Например, можно создать задание для службы cron и воспользоваться в нем командой:
service auditd rotate
Под капотом она посылает процессу auditd сигнал USR1, который выполняет ротацию файлов:
rotate)
log_daemon_msg "Rotating $DESC logs" "$NAME"
start-stop-daemon --stop --signal USR1 --quiet --pidfile "$PIDFILE"
--name "$NAME"
log_end_msg $?
При этом для max_log_file_action необходимо задать значение IGNORE. Значение из директивы num_logs будет продолжать ограничивать количество хранимых файлов журнала.
- /etc/audit/rules.d/*.rules — набор файлов, содержащих правила мониторинга системных событий. Про синтаксис правил можно почитать здесь, а более подробно — здесь. Я же расскажу о том, чего не найти в официальной документации ;)
Вместо перечисления конкретных системных вызовов для отслеживания применительно к какому-либо файлу можно оперировать параметрами для -F perm или -p. За каждым типом доступа, который можно указать в этих флагах, кроется своя группа системных вызовов.
r | w | x | a |
Для каталогов и файлов: open, openat, openat2 с флагом 'r' | Для каталогов и файлов: open, openat, openat2 с флагом 'w' Для файлов: acct | Для файлов: execve, execveat | Для каталогов и файлов: chmod, fchmod, fchmodat |
Например, из таблицы 1 можно узнать, что удаление файлов кроется за флагом w (запись), что поначалу может быть неочевидно.
После того как все правила мониторинга будут добавлены в файл, необходимо отправить их в подсистему аудита. Для применения правил из отдельного файла можно воспользоваться командой:
auditctl -R <путь_к_файлу>
При обнаружении ошибки в одной из строк файла дальнейшие правила не будут добавляться в итоговый список. Чтобы игнорировать такие ошибки, нужно в начале файла прописать строку "-i".
Если же нужно применить правила из всех файлов каталога сразу, можно воспользоваться утилитой augenrules. Она представляет собой bash-скрипт, который объединяет содержимое всех файлов *.rules в файл /etc/audit/audit.rules и применяет к нему команду auditctl -R. Этот же скрипт выполняется при перезапуске службы auditd, поэтому вручную вносить какие-либо изменения в /etc/audit/audit.rules не рекомендую. Для игнорирования ошибок, про которые я писал чуть выше, строку "-i" нужно прописать в начале первого файла (файлы идут в алфавитном порядке).
Диспетчер аудита
Отдельный компонент, способный напрямую принимать события от службы auditd и перенаправлять их в разные точки назначения, используя собственные плагины. Я буду рассматривать только плагин Syslog, включенный в стандартный набор. Посмотрим на его конфигурационные файлы:
- /etc/audisp/audispd.conf и /etc/audisp/plugins.d/syslog.conf — комбинация файлов, характерная для версий auditd ниже 3.0. Задает параметры непосредственно диспетчера и плагина Syslog.
audispd.conf
q_depth = 250
overflow_action = SYSLOG
priority_boost = 4
max_restarts = 10
name_format = HOSTNAME
#name = mydomain
plugin_dir = /etc/audisp/plugins.d/
syslog.conf
active = yes
direction = out
path = builtin_syslog
type = builtin
args = LOG_LOCAL6
format = string
Для транспортировки событий нужно активировать плагин, выставив active в yes. По умолчанию они отправляются в сокет Syslog с facility и priority, равными LOG_USER и LOG_INFO соответственно. Через параметр args можно поменять что-то одно или сразу оба. Возможные значения:
- для facility: LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_AUTH, LOG_AUTHPRIV, LOG_DAEMON, LOG_SYSLOG, LOG_USER;
- для priority: LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_WARNING, LOG_ERR, LOG_CRIT, LOG_ALERT, LOG_EMERG.
Пример одновременной смены facility и priority:
args = LOG_LOCAL6 LOG_INFO
- /etc/audit/auditd.conf и /etc/audit/plugins.d/syslog.conf — файлы из новых версий auditd. Про auditd.conf я уже рассказывал выше. Как и про syslog.conf, который сменил местоположение и значения директив path и type, но все так же определяет параметры для плагина Syslog.
syslog.conf
active = yes
direction = out
path = /sbin/audisp-syslog
type = always
args = LOG_INFO
format = string
Для директивы args в новых версиях появляется возможность задать значение interpret. Его функциональность схожа с той, которая становится доступна, если в файле auditd.conf для директивы log_format задать значение ENRICHED. С чем удобнее работать — решать вам. Мы рекомендуем использовать ENRICHED, чтобы сохранить совместимость нормализаций, а также из-за большего объема предоставляемых в событиях данных.
log_format = ENRICHED
type=SERVICE_START msg=audit(1748533040.162:1531): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=unconfined msg='unit=auditd comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success' UID="root" AUID="unset"
args = interpret
type=SERVICE_START msg=audit(05/29/25 15:36:01) : pid=1 uid=root auid=unset ses=unset subj=unconfined unit=auditd comm=systemd exe=/usr/lib/systemd/systemd hostname=? addr=? terminal=? res=success
Стоит заметить, что в args можно указать максимум два аргумента. Так что задать одновременно facility, priority и interpret не получится. Кроме того, если с помощью args не менять facility с LOG_USER на что-то другое, то события будут передаваться дальше с заголовком audisp-syslog[...]. В остальных случаях будет выставлен audispd[...].
Подсистема журналирования systemd
Компонент подсистемы инициализации systemd, который представляет собой службу systemd-journald с набором различных модулей-сокетов для приема и отправки событий. Журналы хранятся в виде бинарных файлов, для просмотра которых используется утилита journalctl.

Модули сокетов
systemd-journald-audit.socket
Модуль привязывается к системному netlink-сокету, который, в свою очередь, общается с подсистемой аудита.
[Socket]
ListenNetlink=audit 1
Мы рекомендуем клиентам отключать его: когда он работает одновременно с диспетчером аудита, возникает дублирование событий auditd в журнале. А оно нам совсем ни к чему, ведь ресурсы узла и MaxPatrol SIEM для их обработки не безграничны.
Пример дублирования внутри журнала system:
May 25 18:27:19 host.name audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 subj=unconfined msg='unit=auditd comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
May 25 18:27:19 host.name audisp-syslog[1411]: node=host.name type=SERVICE_START msg=audit(1748197639.934:1280): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=unconfined msg='unit=auditd comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success' UID="root" AUID="unset"
systemd-journald-dev-log.socket
Модуль привязывается к сокету /run/systemd/journal/dev-log. При этом файл /dev/log — это символическая ссылка на /run/systemd/journal/dev-log. Для служб, которые привыкли отправлять свои события в /dev/log, к примеру с помощью функции syslog(3), точка для отправки остается прежней.
[Socket]
ListenDatagram=/run/systemd/journal/dev-log
Symlinks=/dev/log
В качестве эксперимента можно попробовать отправить событие, используя Python:
import syslog
syslog.openlog(ident="syslog", logoption=syslog.LOG_PID, facility=syslog.LOG_USER) syslog.syslog(syslog.LOG_INFO, "Test syslog") syslog.closelog()
Получим событие в журнале:
May 25 21:07:36 host.name syslog[4095110]: Test syslog
systemd-journald.socket
Модуль привязывается к сокетам /run/systemd/journal/stdout и /run/systemd/journal/socket, которые принимают по нативному протоколу журнала systemd события, отправляемые извне с помощью функции sd_journal_print(3).
[Socket]
ListenStream=/run/systemd/journal/stdout
ListenDatagram=/run/systemd/journal/socket
В качестве эксперимента, как и в случае с syslog, попробуем отправить событие с помощью Python:
from systemd import journal
journal.send("Test native journald")
Получим событие:
May 25 21:12:27 host.name python3[4095335]: Test native journald
Служба журналирования
/etc/systemd/journald.conf — очень простой для анализа файл конфигурации. Закомментированные строки содержат директивы со значениями по умолчанию. Полный список директив можно изучить здесь.
[Journal]
#Storage=auto
#ForwardToSyslog=yes
#ForwardToKMsg=no
#ForwardToConsole=no
#ForwardToWall=yes
#ReadKMsg=yes
# ...
Нам интересны те, которые отвечают за маршрутизацию событий:
- Storage. При значении persistent журналы сохраняются на диске в каталоге /var/log/journal. Если он существует, а значение директивы выставлено в auto, это будет равнозначно persistent. При значении volatile журналы сохраняются в каталоге /run/log/journal, который очищается при каждой перезагрузке узла. При значении none журналы не сохраняются локально, но продолжают пересылаться в другие точки назначения, задаваемые через директивы ForwardTo*.
- ForwardToSyslog. При установке значения в yes события будут отправляться в сокет /run/systemd/journal/syslog. Если планируется использовать RSyslog с модулем imuxsock, необходимо включить эту директиву.
- ReadKMsg. Установка значения в yes позволит забирать события, которые шлются ядром в файл /dev/kmsg.
Служба systemd-journald также имеет встроенный механизм ротации собственных журналов, которая может выполняться как на основе размера файлов, так и по времени. Мы не будем подробно разбирать эту тему, но для общего ознакомления приведу краткую выжимку.
За ротацию по размеру отвечают директивы System* (для /var/log/journal) и Runtime* (для /run/log/journal):
- *MaxFileSize. Максимальный размер одного файла журнала, по достижении которого происходит ротация.
- *MaxFiles. Максимальное количество файлов (при его превышении более старые файлы удаляются).
- *MaxUse. Максимальный размер всех файлов (при его превышении более старые файлы удаляются).
- *KeepFree. Размер свободного места в файловой системе, при достижении которого более старые файлы будут удаляться.
За ротацию по времени отвечают директивы:
- MaxFileSec. Продолжительность ведения одного файла журнала.
- MaxRetentionSec. Время жизни файла, по прошествии которого он удаляется.
Комбинация этих директив может порождать разные неожиданные ситуации, поэтому следует внимательно подбирать для них значения.
Система RSyslog
Самая распространенная система для обработки и маршрутизации событий. Представляет собой службу rsyslogd с набором различных модулей для взаимодействия с источниками и точками назначения.

Модули
Каждый модуль RSyslog заточен под тот или иной источник (модули с именами im*) или точку назначения (имена om*). Они загружаются в конфигурацию с помощью директивы module(load="<имя_модуля>"). Дополнительные параметры можно изучить в разделе Module Parameters документации RSyslog для каждого конкретного модуля (пример для imfile).
Системные события могут быть получены через модули imuxsock или imjournal. Однако разработчики RSyslog предупреждают, что использование imjournal довольно затратно по потреблению ресурсов. Если вам не нужно получать особым образом структурированные данные, лучше использовать imuxsock.
Для отправки данных на удаленный сервер, как правило, используется модуль omfwd. Он встроенный, поэтому его можно не загружать с помощью module(). Если же вы захотите поменять его параметры, используйте синтаксис module(load="builtin:omfwd" <ваши_параметры>).
Настройка службы
/etc/rsyslog.conf
Настройка приема событий выполняется с помощью директивы input(type="<имя_im_модуля>"). Дополнительные параметры можно посмотреть в разделах Input Parameters официальной документации для каждого конкретного модуля. Отправка событий настраивается внутри директивы action(type="<имя_om_модуля>"). Дополнительные поля для нее можно изучить в разделах Action Parameters для каждого конкретного модуля.
Замечу, что для некоторых im-модулей внутри input() доступна директива Ruleset. Она позволяет привязать выбранный источник к конкретному набору правил отправки событий вовне. Каждый такой набор задается с помощью директивы ruleset() и содержит в себе один или несколько action(). Все action(), заданные вне явно объявленных ruleset(), попадают в стандартный набор с именем RSYSLOG_DefaultRuleset.

Проверить, какие модули запущены в данный момент, можно с помощью команды:
top -H -p pgrep rsyslog

Для более тонкой настройки маршрутизации событий используются различные фильтры. После их применения события могут быть перенаправлены на один или несколько action() (см. пример 1) либо на конкретный ruleset() (см. пример 2).
Пример 1
module(load="imfile")
input(
type="imfile"
File="/var/log/messages"
Severity="info"
Facility="local7"
# Ruleset="RSYSLOG_DefaultRuleset"
)
if $syslogfacility-text == "local7" and $syslogpriority-text == "info" then {
action(
type="omfwd"
target="10.10.10.10"
protocol="udp"
port="514"
)
action(
type="omfwd"
target="10.10.10.11"
protocol="udp"
port="514"
)
}
Пример 2
module(load="imfile")
input(
type="imfile"
File="/var/log/messages"
Severity="info"
Facility="local7"
Ruleset="forward_to_siem"
)
ruleset(
name="forward_to_siem"
action(
type="omfwd"
target="10.10.10.10"
protocol="udp"
port="514"
)
action(
type="omfwd"
target="10.10.10.11"
protocol="udp"
port="514"
)
)
if $syslogfacility-text == "local7" and $syslogpriority-text == "info" then call forward_to_siem
При должной сноровке можно выстраивать цепочки для перемещения событий из одной точки в другую. Здесь все зависит от вашей фантазии.
Система Syslog-NG
Менее популярная, чем RSyslog, но легко доступная для установки система обработки событий. Стоит оговориться, что в Linux в один момент времени может быть запущена только одна из этих систем (если вы, конечно, не энтузиаст и не придумали возможность это обойти).

Модули
Для сбора системных событий используется модуль system(). Под капотом он скрывает набор других фильтров и параметров — в зависимости от операционной системы и ее конфигурации. В Linux это либо модуль systemd-journal(), собирающий события из журнала systemd, либо комбинация из модулей unix-dgram() (собирает события из /dev/log) и file() (собирает события из /dev/kmsg или /proc/kmsg). Чтобы узнать содержимое system() в вашей системе, можно воспользоваться специальным скриптом из официального GitHub-репозитория Syslog-NG.
События auditd, в свою очередь, могут собираться из файла /var/log/audit/audit.log с помощью модуля linux-audit(). Но если вы настроили диспетчер аудита для отправки событий в сокет Syslog, использовать отдельный модуль необязательно.
Для передачи данных на удаленный сервер рекомендуем использовать модуль network() вместо устаревших udp() и tcp(). Протокол передачи при этом указывается во вложенной директиве transport(). Информацию о других модулях для приема и отправки событий можно почитать в официальной документации.
Настройка службы
/etc/syslog-ng/syslog-ng.conf

source: перечень источников событий
source src {
unix-dgram("/dev/log");
internal();
file("/proc/kmsg" log_prefix("kernel: "))
};
filter: фильтр для событий
filter auth {
facility(auth, authpriv)
and not filter(debug);
};
destination: перечень точек назначения для отправки событий
destination d_auth {
file("/var/log/auth.log");
};
Затем эти три сущности объединяются в блок log, который описывает одну из цепочек маршрутизации (назовем их так):
log {
source(src);
filter(auth);
destination(d_auth);
};
Внутри одной цепочки можно использовать несколько source(), filter() и destination(). При этом несколько filter() будут объединяться через логическое «И». С помощью таких цепочек, по аналогии с RSyslog, можно реализовывать различные сценарии пересылки событий из одного места в другое — в зависимости от ваших потребностей.
Дальше все события попадают в MaxPatrol SIEM. И здесь я завершаю свой краткий экскурс в мир настроек журналирования Linux. Надеюсь, вы вынесете для себя что-то полезное и станете чуть лучше понимать, как все работает на самом деле. Еще увидимся!