auditd на Linux в 2026: правила аудита, ausearch и интеграция с SIEM
Практическое руководство по настройке auditd на RHEL 9 и Ubuntu 24.04 в 2026: правила sudo, execve и /etc/passwd, поиск через ausearch и пересылка событий в Wazuh или Splunk через audisp-плагины.
auditd это демон подсистемы аудита ядра Linux, который перехватывает системные вызовы и события файловой системы через netlink и пишет структурированные записи в /var/log/audit/audit.log для форензики, соответствия требованиям (PCI DSS, HIPAA, DISA STIG) и обнаружения атак. В отличие от rsyslog и journald, auditd работает на уровне ядра, поэтому события не теряются, даже если процесс успел удалить свой след в пользовательском пространстве. В этом руководстве я разберу, как настроить auditd на RHEL 9 и Ubuntu 24.04 в 2026 году, какие правила стоит добавить сверх STIG и как переслать поток событий в Wazuh или Splunk без потери в 20 000 EPS.
Актуальные версии в 2026: audit 3.1.5 в RHEL 9.x и 3.1.2 в Ubuntu 24.04. Upstream перескочил с 3.1.5 сразу на 4.0 (никакой 3.2 не было) и добавил TLS в удалённом логировании в 4.2.
Начиная с audit 3.0 отдельного демона audispd больше нет: его функциональность встроена в auditd, а плагины лежат в /etc/audit/plugins.d/, а не в /etc/audisp/.
Правила делятся на watches (-w) для файлов и syscall rules (-a) для системных вызовов. Каждое правило обязательно должно иметь тег -k, иначе поиск в ausearch превращается в grep по трём миллионам строк.
STIG SCAP Benchmark для RHEL 9 (V1R1) содержит 416 правил, десятки касаются именно аудита. Большинство из них создают лавину событий в контейнеризованных средах и требуют фильтрации.
Пересылку в SIEM делают через плагины audisp-remote, audisp-syslog или audisp-af_unix для Wazuh. Прямой tail через rsyslog imfile ломается на ротации.
Флаг -e 2 замораживает конфигурацию до перезагрузки: правила нельзя ни добавить, ни удалить даже из-под root. Это требование STIG, но им легко себе выстрелить в ногу.
Что делает auditd и чем он отличается от syslog
Подсистема аудита Linux состоит из трёх частей: kauditd-потока в ядре, netlink-сокета AUDIT_NETLINK_GRP_READLOG и пользовательского демона auditd, который вытаскивает записи из сокета и пишет их на диск. Правила загружаются один раз через auditctl и живут в ядре. Процесс auditd можно вообще убить, а kauditd продолжит собирать события в кольцевой буфер до тех пор, пока не переполнится backlog_limit.
Это принципиально отличает его от rsyslog и systemd-journald. Rsyslog читает поток от приложений, доверяя им форматирование. Злоумышленник с root может подменить бинарник и «забыть» логировать. Journald завязан на структурированные поля от systemd-юнитов и тоже работает в userspace. А вот auditd перехватывает syscall до того, как ядро отдаёт управление обратно процессу. То есть даже rm -f /var/log/audit/audit.log оставит после себя событие PATH с полным контекстом (uid, auid, tty, exe, comm).
Честно говоря, на банковских проектах, где я это внедрял, auditd был единственным источником, который принимают форензик-аудиторы без вопросов. Причина в том, что записи содержат auid (audit UID), устанавливаемый PAM при логине и неизменяемый до конца сессии. Если пользователь сделал sudo -i и работает как root, обычный who покажет root, а auditd отдаст исходный логин.
Установка auditd на RHEL 9 и Ubuntu 24.04
На RHEL 9 пакет уже установлен по умолчанию, а вот плагины нет. На Ubuntu 24.04 всё ставится вручную. Проверьте версию перед началом: с audit 3.1 многое поменялось, и статьи 2019 года про audispd уже не применимы.
Если enabled равен 0, добавьте audit=1 в параметры загрузки ядра через grubby --update-kernel=ALL --args="audit=1 audit_backlog_limit=8192" и перезагрузитесь. Некоторые облачные образы (особенно AWS AL2023 и Azure RHEL) поставляются с audit=0 по умолчанию. Это единственный legit случай, когда демон запущен, а событий нет.
Синтаксис правил: watches, syscall и ключи
Есть два вида правил, и путать их — самая частая ошибка новичков:
Watches (-w /path -p [rwxa] -k key) следят за путём файла или каталога. Реализованы поверх inotify, работают быстро, но не срабатывают, если файл открывается через жёсткую ссылку в другом месте.
Syscall rules (-a action,list -S syscall -F field=value -k key) фильтруют вызовы ядра по 64 полям (uid, auid, arch, exe, cwd и т. д.). Дают полный контекст, но каждое дополнительное правило стоит CPU-циклов.
Ключевой параметр: всегда указывайте -k. Тег становится полем key= в записи и позволяет фильтровать через ausearch -k имя_ключа. Без него события смешиваются в общей ленте, и найти нужное можно только через ausearch --raw | grep, что на нагруженном сервере убьёт I/O.
Пример разницы:
# Watch: срабатывает при любом изменении /etc/shadow
-w /etc/shadow -p wa -k identity
# Syscall rule: то же самое, но только когда исполняется от non-root пользователя
-a always,exit -F arch=b64 -S openat -F path=/etc/shadow -F success=1 \
-F auid>=1000 -F auid!=-1 -k shadow-access-by-user
Правила пишутся в файлы /etc/audit/rules.d/*.rules по одному правилу на строку. Утилита augenrules --load собирает их в единый /etc/audit/audit.rules в алфавитном порядке имён файлов. Поэтому назовите свои файлы с префиксом (например, 10-base.rules, 50-stig.rules, 99-immutable.rules). Порядок критичен, потому что первое совпавшее правило выигрывает.
Практический ruleset: sudo, /etc/passwd, execve и STIG
Ниже приведён базовый набор, который я использую на всех hardened-серверах. Он покрывает 80% того, что реально нужно для аудита: изменения пользователей, sudo, монтирование, загрузку модулей ядра и выполнение команд под root. Полный STIG-ruleset для RHEL 9 можно взять из DISA STIG SCAP Benchmark, но перед деплоем в контейнерную среду его нужно фильтровать. Иначе получите десятки тысяч событий в минуту от cAdvisor и containerd.
# /etc/audit/rules.d/50-base.rules
# ---- Изменения identity ----
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/sudoers -p wa -k identity
-w /etc/sudoers.d/ -p wa -k identity
# ---- Использование sudo и su ----
-a always,exit -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=-1 -k priv-esc
-a always,exit -F path=/usr/bin/su -F perm=x -F auid>=1000 -F auid!=-1 -k priv-esc
# ---- Изменения системного времени ----
-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time-change
-w /etc/localtime -p wa -k time-change
# ---- Загрузка модулей ядра ----
-a always,exit -F arch=b64 -S init_module,finit_module,delete_module -k modules
-w /usr/sbin/insmod -p x -k modules
-w /usr/sbin/rmmod -p x -k modules
-w /usr/sbin/modprobe -p x -k modules
# ---- Монтирование ----
-a always,exit -F arch=b64 -S mount,umount2 -F auid>=1000 -F auid!=-1 -k mounts
# ---- Выполнение команд от имени root после sudo ----
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -F auid!=-1 -k rootcmd
# ---- Провал доступа (EACCES/EPERM) ----
-a always,exit -F arch=b64 -S openat -F exit=-EACCES -F auid>=1000 -F auid!=-1 -k access-denied
-a always,exit -F arch=b64 -S openat -F exit=-EPERM -F auid>=1000 -F auid!=-1 -k access-denied
Загрузите набор:
sudo augenrules --load
sudo auditctl -l # проверка, что все правила приняты
Поиск событий: ausearch, aureport и autrace
Три утилиты, без которых логи бесполезны:
ausearch: фильтр по ключам, времени, UID, PID. Основной инструмент для расследований.
aureport: агрегатор с топом файлов, топом пользователей и сводкой авторизаций.
autrace: эквивалент strace, но пишущий в audit.log. Полезен для расследования, но нельзя запускать на процессах, которые уже отслеживаются syscall-правилами (получите бесконечный цикл).
Несколько сценариев из моей практики:
# Все события изменения identity за последние 24 часа
sudo ausearch -k identity --start today --end now -i
# Кто пытался читать /etc/shadow, но получил EACCES?
sudo ausearch -k access-denied --file /etc/shadow -i
# Все sudo-команды пользователя ivan за август
sudo ausearch -k priv-esc --start 2026-08-01 --end 2026-08-31 -ua ivan -i
# Все загрузки модулей ядра, красиво отформатированные
sudo aureport --mods --summary -i
# Топ-10 файлов с провалами доступа
sudo aureport -f --failed --summary -i | head -20
Флаг -i раскрывает UID в имена (из /etc/passwd) и syscall-номера в имена, без него вы читаете сырые числа. Флаг -ua ищет по audit UID, а не по effective UID, поэтому находит действия пользователя даже после sudo -i.
Для длительных расследований я обычно выгружаю нужный срез в отдельный файл и уже там ковыряюсь через jq:
Прямой tail /var/log/audit/audit.log через rsyslog imfile? Самый популярный совет из статей десятилетней давности, и он всё ещё регулярно ломается: после ротации через logrotate rsyslog иногда теряет inode и молчит до следующего рестарта. Правильный способ: использовать audisp-плагины, которые работают внутри процесса auditd и получают события напрямую из очереди, до записи на диск.
Начиная с audit 3.0 плагины лежат в /etc/audit/plugins.d/ (а не в /etc/audisp/plugins.d/, как в старых мануалах). Актуальный набор в 2026 году:
audisp-af_unix: сокет для Wazuh-агента (заменил встроенный af_unix в 3.1).
audisp-syslog: форвардит в локальный syslog (для дальнейшей пересылки rsyslog'ом).
audisp-remote: TCP/TLS-пересылка на удалённый auditd (TLS появился в 4.2 upstream).
audisp-filter: предфильтр событий до отправки в плагины (новинка 3.1).
# /etc/audit/plugins.d/af_unix.conf
active = yes
direction = out
path = /sbin/audisp-af_unix
type = always
args = 0640 /var/ossec/queue/ossec/audit
format = string
Wazuh-агент читает этот сокет и переправляет события в manager, где они обогащаются MITRE ATT&CK-тегами. Для Splunk путь другой: включаете audisp-syslog, направляете facility local6 в отдельный файл через rsyslog, и Splunk Universal Forwarder монитирит уже этот файл. Так вы не теряете структурированность и не перегружаете journald.
# /etc/audit/plugins.d/syslog.conf
active = yes
direction = out
path = /sbin/audisp-syslog
type = always
args = LOG_LOCAL6 LOG_INFO
format = string
# /etc/rsyslog.d/30-audit.conf
local6.* /var/log/audit-forward.log
& stop
После правки любого плагина перезапускайте auditd правильным способом: sudo service auditd restart (не systemctl).
Тюнинг производительности и ротация логов
На нагруженном сервере (500+ EPS) стандартные параметры создают три проблемы: переполнение буфера ядра, замедление процессов (auditd блокирует syscall до приёма события) и заполнение /var/log/audit за несколько часов. Основной конфиг живёт в /etc/audit/auditd.conf:
# /etc/audit/auditd.conf — ключевые параметры
max_log_file = 100 # МБ на один файл
num_logs = 20 # хранить 20 ротаций (~2 ГБ суммарно)
max_log_file_action = ROTATE # что делать при достижении лимита
space_left = 500 # МБ свободного места (trigger warning)
space_left_action = SYSLOG # варианты: EMAIL, EXEC, SUSPEND, SINGLE, HALT
admin_space_left = 100
admin_space_left_action = SUSPEND # STIG требует SINGLE или HALT
disk_full_action = SUSPEND
disk_error_action = SUSPEND
flush = INCREMENTAL_ASYNC # NONE / DATA / SYNC / INCREMENTAL_ASYNC
freq = 50 # flush каждые 50 записей
# --- параметры ядра (auditctl) ---
# в /etc/audit/rules.d/00-init.rules
-D # очистить существующие правила
-b 16384 # backlog_limit (размер очереди в ядре)
--backlog_wait_time 30000 # ms ожидания перед drop при переполнении
-f 1 # failure mode: 0=silent, 1=printk, 2=panic
--loginuid-immutable # запрет смены auid после установки
Мониторьте состояние демона: auditctl -s показывает lost (события, потерянные из-за переполнения) и backlog (текущая длина очереди). Если lost растёт, увеличивайте -b или сокращайте набор правил. Также посмотрите параметры sysctl для hardened-ядра: некоторые из них (например, kernel.dmesg_restrict) взаимодействуют с audit-подсистемой.
Как сделать конфигурацию auditd неизменяемой
Флаг -e 2 замораживает конфигурацию до перезагрузки: ни одно правило нельзя ни добавить, ни удалить, даже из-под root. Это требование STIG (SV-258126r958732_rule) и просто хорошая практика: если атакующий получил root, он не сможет спрятать свои следы через auditctl -D. Добавляется всегда последней строкой в правилах:
# /etc/audit/rules.d/99-finalize.rules
-e 2
Значения флага -e:
-e 0: аудит выключен, но правила и очередь работают.
-e 1: аудит включён (по умолчанию).
-e 2: locked, правила заморожены до перезагрузки.
После установки -e 2 изменения правил применяются только через перезагрузку. Это неудобно, но правильно: если вам часто нужно править ruleset «на живую», значит, у вас нет CI/CD-процесса управления конфигурацией. Заведите официальный audit-userspace в pipeline и деплойте через Ansible-роль с notify: reboot, а не через auditctl вручную. Я сам однажды забыл про -e 2 на препрод-сервере и час дебажил, почему augenrules --load не подхватывает новые правила. Все ответы были в dmesg, но кто туда смотрит первым, честно.
Полный список подсистем аудита, включая новые фичи 4.x, задокументирован в Red Hat Security Hardening guide для RHEL 9. Если ваша инфраструктура ещё не мигрировала на audit 4.x, планируйте: TLS-remote-logging из 4.2 закрывает целый класс уязвимостей MITM при пересылке событий через WAN.
Часто задаваемые вопросы
В чём разница между auditd и rsyslog?
Rsyslog собирает сообщения от приложений в пользовательском пространстве и доверяет им форматирование. auditd перехватывает системные вызовы на уровне ядра через netlink, поэтому события фиксируются независимо от того, что делает приложение или атакующий с root-правами. rsyslog удобен для application logs, а auditd остаётся единственно приемлемым источником для форензики и compliance.
Как аудировать выполнение команд конкретным пользователем?
Используйте syscall-правило на execve с фильтром по auid: -a always,exit -F arch=b64 -S execve -F auid=1001 -k user-1001-cmd. Затем ищите через ausearch -k user-1001-cmd -i. auid ставится PAM при логине и неизменяем, поэтому sudo не сбросит его.
Почему auditd заполняет /var/log/audit и как его ротировать?
Стандартные лимиты в /etc/audit/auditd.conf (max_log_file=8, num_logs=5) рассчитаны на десктоп. На сервере поднимите max_log_file до 100 МБ и num_logs до 20, установите max_log_file_action=ROTATE. Не подключайте logrotate, auditd ротирует сам через встроенный механизм.
Можно ли отключить auditd без перезагрузки?
Если не установлен флаг -e 2, то да: sudo auditctl -e 0 остановит запись событий, но kauditd в ядре продолжит работать. Полное отключение с выгрузкой правил делается через auditctl -D && auditctl -e 0. Если конфигурация заморожена (-e 2), только перезагрузка снимет блокировку.
Обязательно ли использовать STIG-ruleset целиком?
Нет, и в контейнеризованных средах категорически не рекомендуется. STIG SCAP Benchmark для RHEL 9 (V1R1, 416 правил) писался под bare-metal и создаёт лавину событий от containerd, kubelet и CNI-плагинов. Используйте STIG как базу, но фильтруйте правила по exe!= для системных бинарников, которые генерируют шум.
Mateusz spent eight years on the Red Hat consulting bench before going independent in 2024, embedded with banks and telcos rolling out RHEL 8 and 9 across regulated estates. Most of that work was SELinux policy debugging, FIPS-mode enablement, and cleaning up the kind of sudoers files that grow organically over a decade.
He holds OSCP and RHCE, and maintains a small set of Ansible roles for STIG-hardened RHEL builds that a few European credit unions now run in production. Before Red Hat he was a junior sysadmin at Allegro in Poznan, mostly babysitting Postfix and learning why you don't run updatedb on an NFS root.
Mateusz writes about the boring half of Linux security: package signing, audit daemon tuning, and the unglamorous work of actually reading journalctl output before paging anyone.
Пошаговая настройка CrowdSec 1.6 на Linux: агент, LAPI, bouncer для nftables, AppSec WAF перед nginx, защита SSH от bruteforce и подключение к коллективному Blocklist API с примерами команд и типичными ошибками.
Как подписывать контейнеры без приватных ключей: Cosign v2.4 keyless в GitHub Actions, проверка через Kyverno в Kubernetes, SLSA-provenance и SBOM-attestations. Практический пример workflow и типичные ошибки.
Trivy 0.65+ для DevSecOps: сканирование контейнеров, Terraform и Kubernetes YAML, генерация SBOM (CycloneDX, SPDX), поиск секретов и готовые пайплайны для GitHub Actions, GitLab CI и Trivy Operator.