Есть вещи, о которых узнаёшь слишком поздно. Файл /etc/sudoers был изменён три дня назад - кем, в котором часу, с какого терминала. Исполняемый файл в /usr/bin вдруг оказался другим размером. Кто-то редактировал /etc/cron.d в два часа ночи. Стандартные системные логи на этот вопрос не ответят: они просто не созданы для такого уровня детализации. Именно здесь начинается территория auditd - подсистемы аудита Linux, которая работает на уровне ядра и перехватывает системные вызовы ещё до того, как они отразятся в каких-либо прикладных логах.
Auditd - это не просто "ещё один логгер". Это разница между "что-то случилось" и "вот кто это сделал, вот когда, вот с какого процесса". Особенно ценная разница на продакшн-серверах, где цена ошибки высока, а цена незамеченного вмешательства - ещё выше.
Архитектура подсистемы и установка
Auditd устроен в два слоя. Первый - kauditd, компонент ядра, который перехватывает системные вызовы и пропускает их через фильтры. Второй - демон auditd в пользовательском пространстве, который принимает события от ядра и записывает их в лог. Между ними - буфер, размер которого критически влияет на поведение системы при высокой нагрузке: если буфер переполняется, ядро либо отбрасывает события, либо блокирует системные вызовы в ожидании освобождения места - в зависимости от настроек.
На Debian и Ubuntu установка выглядит так:
apt install auditd audispd-plugins -y
На RHEL, CentOS и Rocky Linux пакет чаще всего уже присутствует в системе, но если нет:
dnf install audit audit-libs -y
После установки нужно убедиться, что демон запущен и включён в автозагрузку:
systemctl enable --now auditd
systemctl status auditd
Проверить состояние самой подсистемы аудита, включая размер буфера и количество потерянных событий, позволяет команда:
auditctl -s
Вывод покажет строку enabled 1 - подсистема активна. Поле lost отражает количество событий, которые были отброшены из-за переполнения буфера. На нагруженных серверах это значение стоит мониторить: если оно растёт, буфер слишком мал и его нужно увеличивать через параметр -b в файле правил.
Базовая конфигурация демона и ротация логов
Основной конфигурационный файл auditd находится по пути /etc/audit/auditd.conf. Большинство его параметров имеют разумные значения по умолчанию, но несколько позиций заслуживают осознанного решения перед тем, как на сервере появятся первые правила мониторинга.
Самое важное - это то, что происходит при заполнении диска. Параметр space_left_action определяет, что делать, когда свободное место опускается ниже порога space_left (в мегабайтах). Значение SYSLOG отправляет предупреждение в системный лог. Значение EMAIL шлёт письмо администратору. Значение HALT останавливает систему - жёстко, но именно это требуют некоторые стандарты безопасности, поскольку сервер без аудита для них неприемлем. Параметр admin_space_left_action = HALT задаёт поведение при критически низком уровне свободного места.
Рабочая конфигурация для продакшн-сервера выглядит примерно так:
# /etc/audit/auditd.conf
log_file = /var/log/audit/audit.log
log_format = ENRICHED
max_log_file = 50
num_logs = 10
max_log_file_action = ROTATE
space_left = 500
space_left_action = SYSLOG
admin_space_left = 100
admin_space_left_action = HALT
flush = INCREMENTAL_ASYNC
freq = 50
Параметр log_format = ENRICHED заслуживает отдельного комментария. В этом режиме auditd разрешает числовые идентификаторы UID и GID в имена пользователей прямо при записи в лог, а не при чтении. Это удобно - записи сразу читаемы без дополнительных утилит. Но есть нюанс: если пользователь был удалён после того, как событие было записано, лог всё равно сохранит его имя, а не просто безликий номер.
После изменений в auditd.conf демон перезапускается особым способом - не через restart, а через reload, чтобы избежать потери буферизованных событий:
service auditd reload
Именно service, а не systemctl - это намеренное ограничение, которое не позволяет случайно потерять записи в процессе рестарта.
Правила мониторинга - как устроена логика и синтаксис
Правила auditd делятся на два типа, и их смешение в голове приводит к ошибкам. Первый тип - файловые наблюдатели (-w), которые отслеживают обращения к конкретным файлам и директориям через механизм inotify ядра. Второй тип - правила системных вызовов (-a), которые перехватывают execve, open, unlink и другие syscall с детальной фильтрацией по uid, pid, архитектуре и прочим параметрам. Файловые наблюдатели проще в написании, правила syscall - мощнее и точнее.
Файловые правила имеют такой синтаксис:
-w <путь> -p <права> -k <ключ>
Флаг -p принимает комбинации из четырёх букв: r (read), w (write), x (execute), a (attribute change - смена прав, владельца, временных меток). Флаг -k задаёт произвольную метку, по которой потом можно фильтровать лог с помощью ausearch -k.
Правила системных вызовов выглядят иначе:
-a always,exit -F arch=b64 -S execve -F uid=0 -k rootcmd
Здесь -a always,exit означает "всегда создавать событие при завершении системного вызова". Параметр arch=b64 - критически важный фильтр: на 64-битных системах одни и те же действия могут выполняться через 32-битный и 64-битный слои syscall. Если написать правило только для b64, злоумышленник теоретически может обойти его через 32-битный execve. Правила для серьёзного мониторинга всегда пишутся парами - для b64 и b32.
Полный набор правил для мониторинга /etc и критических файлов
Правила хранятся не в /etc/audit/audit.rules напрямую, а в файлах в директории /etc/audit/rules.d/. При старте системы утилита augenrules собирает их в итоговый audit.rules в алфавитном порядке по имени файла. Это позволяет разбивать правила по логическим блокам: 10-base.rules для управляющих параметров, 30-etc.rules для мониторинга конфигурационных файлов, 50-binaries.rules для бинарников, 99-finalize.rules для финальной блокировки.
Управляющий файл с базовыми параметрами:
# /etc/audit/rules.d/10-base.rules
# Очистить предыдущие правила
-D
# Буфер для событий - увеличить при потерях
-b 16384
# Режим работы: 1 - активен, 2 - иммутабельный (требует перезагрузки для смены правил)
-e 1
Блок мониторинга критических файлов в /etc:
# /etc/audit/rules.d/30-etc.rules
# Файлы управления пользователями и группами
-w /etc/passwd -p wa -k user_management
-w /etc/shadow -p wa -k user_management
-w /etc/group -p wa -k user_management
-w /etc/gshadow -p wa -k user_management
# Права sudo
-w /etc/sudoers -p wa -k sudo_rules
-w /etc/sudoers.d/ -p wa -k sudo_rules
# SSH-конфигурация
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/ssh/authorized_keys -p wa -k ssh_keys
# Планировщик задач
-w /etc/cron.d/ -p wa -k cron_jobs
-w /etc/cron.daily/ -p wa -k cron_jobs
-w /etc/cron.weekly/ -p wa -k cron_jobs
-w /etc/crontab -p wa -k cron_jobs
# PAM и аутентификация
-w /etc/pam.d/ -p wa -k pam_config
-w /etc/security/ -p wa -k security_config
# Сетевая конфигурация
-w /etc/hosts -p wa -k network_config
-w /etc/resolv.conf -p wa -k network_config
-w /etc/network/ -p wa -k network_config
-w /etc/NetworkManager/ -p wa -k network_config
# Конфигурация systemd и автозагрузки
-w /etc/systemd/ -p wa -k systemd_config
-w /etc/init.d/ -p wa -k init_scripts
# Сам конфигурационный каталог auditd - чтобы не пропустить изменение правил
-w /etc/audit/ -p wa -k audit_config
Наблюдение за директорией /etc/audit/ - деталь, которую часто упускают. Если кто-то изменил правила auditd или отключил демон, это тоже должно попасть в лог. Аудит должен мониторить сам себя - иначе он слеп к наиболее изощрённым действиям.
Мониторинг бинарных файлов через системные вызовы
Мониторинг бинарников - задача другого уровня сложности. Файловый наблюдатель -w /usr/bin/passwd -p x технически работает, но у него есть ограничение: он не покажет аргументы, с которыми был запущен файл, и не раскроет полный контекст вызова. Для бинарников правильный подход - правила на системный вызов execve, который ядро вызывает при запуске любого исполняемого файла.
# /etc/audit/rules.d/50-binaries.rules
# Все команды, выполняемые от имени root - обе архитектуры
-a always,exit -F arch=b64 -F euid=0 -S execve -k root_commands
-a always,exit -F arch=b32 -F euid=0 -S execve -k root_commands
# Команды, выполняемые через sudo (auid - исходный uid до смены через sudo)
-a always,exit -F arch=b64 -S execve -F auid>=1000 -F auid!=-1 -F uid=0 -k sudo_exec
-a always,exit -F arch=b32 -S execve -F auid>=1000 -F auid!=-1 -F uid=0 -k sudo_exec
# Инструменты управления пакетами - любые изменения в составе ПО
-w /usr/bin/apt -p x -k pkg_management
-w /usr/bin/apt-get -p x -k pkg_management
-w /usr/bin/dpkg -p x -k pkg_management
-w /usr/bin/rpm -p x -k pkg_management
-w /usr/bin/yum -p x -k pkg_management
-w /usr/bin/dnf -p x -k pkg_management
# Инструменты изменения прав и владельца
-w /usr/bin/chmod -p x -k permission_change
-w /usr/bin/chown -p x -k permission_change
-w /usr/bin/chattr -p x -k permission_change
# Инструменты управления пользователями
-w /usr/sbin/useradd -p x -k user_ops
-w /usr/sbin/usermod -p x -k user_ops
-w /usr/sbin/userdel -p x -k user_ops
-w /usr/sbin/groupadd -p x -k user_ops
# Загрузка и выгрузка модулей ядра
-w /sbin/insmod -p x -k kernel_modules
-w /sbin/rmmod -p x -k kernel_modules
-w /sbin/modprobe -p x -k kernel_modules
-a always,exit -F arch=b64 -S init_module -S delete_module -k kernel_modules
# Изменение атрибутов файлов setuid/setgid в системных каталогах
-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat \
-F dir=/usr/bin -F perm=x -k suid_change
После добавления правил их нужно применить через augenrules и убедиться, что они загружены корректно:
augenrules --load
auditctl -l
Вывод auditctl -l покажет все активные правила именно в том виде, в котором они воспринимаются ядром, что позволяет обнаружить ошибки синтаксиса, не дожидаясь пока они проявятся в логах отсутствием нужных событий.
Иммутабельный режим - как защитить правила от изменений
Есть одна ситуация, которую стоит обдумать заранее: что если злоумышленник получил root-доступ и первым делом отключил или изменил правила auditd? По умолчанию это возможно - команда auditctl -D удаляет все правила в одно мгновение, не оставляя следов. Именно для защиты от этого сценария существует иммутабельный режим.
Директива -e 2, добавленная в конец файла правил, переводит подсистему аудита в режим, при котором любые попытки изменить правила через auditctl возвращают ошибку. Единственный способ снять блокировку - перезагрузить систему. Это создаёт окно, в котором ядро загрузит правила из файлов заново.
# /etc/audit/rules.d/99-finalize.rules
# Сделать конфигурацию иммутабельной до следующей перезагрузки
-e 2
Иммутабельный режим - это осознанный компромисс. С одной стороны, он делает систему аудита значительно устойчивее к взлому. С другой - добавление нового правила потребует перезагрузки сервера. Для продакшн-серверов, где безопасность важнее операционного удобства, это разумный выбор. Для серверов в активной разработке, где правила регулярно меняются, режим -e 1 практичнее.
Проверить текущий режим:
auditctl -s | grep enabled
# enabled 2 - иммутабельный
# enabled 1 - обычный активный
Анализ логов через ausearch и aureport
Сырой лог /var/log/audit/audit.log - это поток машиночитаемых записей, где каждое событие может занимать несколько строк разных типов: SYSCALL, PATH, EXECVE, CWD. Читать его напрямую можно, но утомительно. Две утилиты - ausearch и aureport - превращают эту массу данных в удобные отчёты.
ausearch работает как умный фильтр. Он умеет группировать связанные записи по идентификатору события, переводить числовые UID в имена пользователей (флаг -i) и ограничивать поиск временным диапазоном:
# Все события по ключу за сегодня
ausearch -k sudo_rules --start today -i
# Что менялось в /etc/passwd
ausearch -f /etc/passwd -i
# Все команды, выполненные конкретным пользователем
ausearch -ua admin --start this-week -i
# Только неудачные попытки
ausearch -k root_commands --start recent -i --success no
aureport работает на уровне выше - он строит сводные отчёты по всей базе событий. Это особенно полезно для регулярного аудита: запустил раз в неделю, просмотрел аномалии:
# Сводный отчёт по файловым событиям с расшифровкой
aureport -f -i --start this-week
# Отчёт по выполненным командам
aureport -x -i --start today
# Все неудачные события
aureport --failed
# Краткая сводка по всем типам событий
aureport --summary
Комбинирование двух утилит даёт дополнительные возможности. Например, найти через ausearch все события по ключу, передать сырой вывод в aureport и получить структурированный файловый отчёт именно по этому срезу:
ausearch -k pkg_management --start this-month --raw | aureport -f -i
Такой конвейер покажет полный список файлов, которых касался менеджер пакетов за месяц - удобно для инвентаризации изменений в составе установленного ПО.
Отправка событий в централизованное хранилище
На серверах, которых несколько, локальное хранение логов создаёт проблему: при компрометации сервера атакующий может уничтожить и логи. Решение - отправлять события аудита на отдельный сервер в реальном времени через плагин audisp-remote.
На сервере-приёмнике в auditd.conf добавляют:
tcp_listen_port = 60
tcp_listen_queue = 5
tcp_max_per_addr = 1
tcp_client_max_idle = 0
На клиентских серверах настраивают плагин:
# /etc/audisp/plugins.d/au-remote.conf
active = yes
direction = out
path = /sbin/audisp-remote
type = always
format = string
# /etc/audisp/audisp-remote.conf
remote_server = <IP сервера аудита>
port = 60
transport = tcp
После перезапуска демона события начнут поступать на центральный сервер. Такая архитектура не только защищает логи от уничтожения, но и открывает возможность подключения SIEM-систем к единой точке сбора данных, что значительно упрощает корреляцию событий между серверами.
Auditd, настроенный с вниманием к деталям, превращается из фонового демона в полноценную систему раннего обнаружения. Он не остановит атаку, но он сделает её видимой - а это уже половина победы.