Когда на VDS крутится обычный веб-стек Nginx + PHP-FPM, большая часть расследований начинается с простых вопросов: кто поменял конфиг, почему внезапно изменились права на каталог сайта, откуда в /var/www появился незнакомый PHP-файл, какой пользователь правил pool PHP-FPM перед падением сайта. По логам Nginx и PHP-FPM такие вещи часто не видно: веб-сервер пишет запросы и ошибки приложения, но не фиксирует операции с файлами на уровне ядра.
Для этого в Linux есть auditd — демон подсистемы Linux Audit. Он получает события от ядра, пишет их в /var/log/audit/audit.log, а администратор затем разбирает их через auditctl, ausearch и aureport. В этой статье настроим auditd linux-подходом для VDS: без попытки логировать всё подряд, но с полезными правилами для /etc, Nginx, PHP-FPM и веб-корня /var/www.
Auditd не заменяет резервные копии, контроль целостности, CI/CD и нормальные права доступа. Его задача — дать доказуемый след: что изменилось, когда, каким пользователем и через какой процесс.
Что именно стоит аудировать на веб-сервере
Главная ошибка при первом знакомстве с auditd — включить аудит на слишком широкие каталоги и получить гигабайты шума. На VDS это особенно неприятно: диск ограничен, лишняя запись в лог конкурирует с сайтом и базой, а полезные события тонут среди временных файлов, кешей и загрузок.
Для типичного сервера с Nginx и PHP-FPM практично разделить аудит на несколько зон.
/etc/nginx— конфигурация Nginx, виртуальные хосты, include-файлы, параметры проксирования и FastCGI./etc/phpна Debian/Ubuntu или/etc/php-fpm.dи/etc/php.iniна RHEL-based системах — настройки PHP-FPM, pool-файлы, лимиты, пользователь процесса.- Критичные части
/etc— sudo, sshd, systemd unit-файлы, cron. В этой статье фокус на веб-стеке, но общий принцип тот же. /var/wwwили конкретный каталог сайта — код приложения, публичные файлы, релизы. Здесь правила нужно подбирать особенно аккуратно.
Для конфигурации обычно достаточно отслеживать запись и изменение атрибутов: права w и a. Для веб-корня всё зависит от способа деплоя. Если релизы выкладываются через rsync, Git, CI/CD или symlink-переключение, аудит всего /var/www может быть слишком шумным. В таком случае лучше аудировать только production-каталог, файл входа приложения, подозрительные исполняемые операции или изменения вне окна деплоя.
Установка auditd
Пакеты называются немного по-разному, но сервис почти везде один — auditd. Ниже команды для популярных семейств ОС. Выполняйте их от root или через sudo.
Debian и Ubuntu
sudo apt update
sudo apt install auditd audispd-plugins
sudo systemctl enable --now auditd
AlmaLinux, Rocky Linux, CentOS Stream, Oracle Linux и Fedora
sudo dnf install audit
sudo systemctl enable --now auditd
Проверьте статус демона и состояние подсистемы аудита:
sudo systemctl status auditd
sudo auditctl -s
В выводе auditctl -s важны поля enabled, backlog, lost и backlog_wait_time. Если lost растёт, ядро теряет события: правил слишком много, диск медленный, логирование не успевает или backlog маловат. Для начала на VDS обычно лучше уменьшить шум правил, а не сразу увеличивать буферы.

Где хранятся правила auditd и как их загружать
Временные правила можно добавить через auditctl, но после перезагрузки они исчезнут. Для постоянной настройки используются файлы в /etc/audit/rules.d/. Затем правила собираются и загружаются командой augenrules.
sudo auditctl -l
sudo augenrules --check
sudo augenrules --load
sudo auditctl -l
Команда auditctl -l показывает активные правила. Команда augenrules --check полезна перед загрузкой: она проверяет, изменился ли итоговый набор. Если вы редактируете правила на удалённой VDS по SSH, не включайте сразу жёсткий immutable-режим -e 2. В этом режиме правила нельзя изменить до перезагрузки, и ошибка может превратить отладку в неприятный квест.
Рабочий порядок такой: сначала загрузить правила, проверить шум и поиск событий, затем добавить их в эксплуатационный набор. Immutable-режим включают только после тестов и при понятном плане отката.
Базовые правила для Nginx, PHP-FPM и /var/www
Создадим отдельный файл правил. Не начинайте его с -D, если не управляете всем набором auditd централизованно: -D очищает предыдущие правила и может случайно отключить аудит, добавленный другими пакетами или вашей системой безопасности.
Debian и Ubuntu
На Debian/Ubuntu конфигурация Nginx обычно лежит в /etc/nginx, а PHP-FPM — в /etc/php, например /etc/php/8.3/fpm/pool.d/. Пользователь веб-процесса часто www-data с uid 33, но лучше проверить.
id -u www-data
sudo install -m 0640 -o root -g root /dev/null /etc/audit/rules.d/50-web-audit.rules
Пример содержимого /etc/audit/rules.d/50-web-audit.rules:
# Nginx configuration
-w /etc/nginx -p wa -k nginx_config
# PHP-FPM configuration on Debian and Ubuntu
-w /etc/php -p wa -k phpfpm_config
# Web root. Narrow this path if deployments are noisy.
-w /var/www -p wa -k webroot_changes
# Execution attempts from web root by PHP-FPM user. Replace 33 if needed.
-a always,exit -F arch=b64 -S execve -F dir=/var/www -F euid=33 -k web_exec_from_webroot
RHEL-based дистрибутивы и Fedora
В AlmaLinux, Rocky Linux, CentOS Stream, Oracle Linux и Fedora Nginx также часто использует /etc/nginx, а PHP-FPM — /etc/php-fpm.d и общий файл /etc/php.ini. Пользователь пула может быть apache, nginx или отдельный пользователь сайта.
id -u nginx
id -u apache
sudo install -m 0640 -o root -g root /dev/null /etc/audit/rules.d/50-web-audit.rules
Пример правил:
# Nginx configuration
-w /etc/nginx -p wa -k nginx_config
# PHP-FPM configuration on RHEL-based systems
-w /etc/php-fpm.d -p wa -k phpfpm_config
-w /etc/php.ini -p wa -k phpfpm_config
# Web root. Narrow this path if deployments are noisy.
-w /var/www -p wa -k webroot_changes
# Execution attempts from web root by PHP-FPM user. Replace 33 with real uid.
-a always,exit -F arch=b64 -S execve -F dir=/var/www -F euid=33 -k web_exec_from_webroot
После записи файла загрузите правила:
sudo augenrules --load
sudo auditctl -l
Если команда ругается на uid, замените число в правиле web_exec_from_webroot на реальный uid пользователя PHP-FPM. Узнать его можно не только через id, но и по процессам:
ps -eo user,pid,comm,args | grep php-fpm
ps -eo user,pid,comm,args | grep nginx
На большинстве современных VDS используется 64-битная система, поэтому в примерах указан arch=b64. Если на сервере действительно запускаются 32-битные бинарники, добавьте отдельное аналогичное правило с arch=b32, но не делайте это «на всякий случай» без проверки — лишние syscall-правила увеличивают шум.
Почему правило на запуск из /var/www полезно
Обычное изменение файла в /var/www ещё не всегда инцидент. CMS, деплой, загрузка медиафайлов и сборка фронтенда могут создавать и менять файлы постоянно. Но попытка выполнить бинарник или скрипт из веб-корня пользователем PHP-FPM — уже сильный сигнал. В нормальной архитектуре PHP-FPM интерпретирует PHP-код, но не должен запускать неизвестные исполняемые файлы из upload-каталогов.
Правило с -S execve ловит системный вызов запуска процесса. Фильтр -F dir=/var/www ограничивает область, а -F euid=33 привязывает событие к эффективному пользователю PHP-FPM. Если у каждого сайта отдельный pool и отдельный пользователь, сделайте несколько правил с разными uid и ключами, например web_exec_site1 и web_exec_site2.
Если на сервере есть легитимные консольные команды приложения, например очереди или artisan/console-команды, запускаемые из каталога релиза, не включайте грубую блокировку на основании одного события. Auditd в этой схеме не блокирует, а показывает факт. Решение принимает администратор или система реагирования.
Проверяем, что события пишутся
Сначала сделайте контролируемое изменение. Например, создайте временный файл в конфигурационном каталоге Nginx и удалите его. Не меняйте боевые конфиги без необходимости.
sudo touch /etc/nginx/auditd-test.conf
sudo rm /etc/nginx/auditd-test.conf
Теперь найдите события по ключу:
sudo ausearch -k nginx_config -i
Ключ -k — одно из самых удобных средств навигации в auditd. Поэтому правила лучше сразу снабжать понятными ключами: nginx_config, phpfpm_config, webroot_changes, web_exec_from_webroot. Через пару месяцев после настройки вы скажете себе спасибо.
Чтобы ограничить поиск недавними событиями, используйте -ts:
sudo ausearch -k nginx_config -ts recent -i
sudo ausearch -k phpfpm_config -ts today -i
sudo ausearch -k webroot_changes -ts yesterday -i
Для конкретного файла полезен фильтр -f:
sudo ausearch -f /etc/nginx/nginx.conf -i
sudo ausearch -f /var/www/example.com/index.php -i
Как читать событие ausearch
Вывод auditd сначала кажется перегруженным. В одном действии может быть несколько записей: SYSCALL, CWD, PATH, иногда PROCTITLE. Это нормально: auditd собирает контекст из разных частей события.
В первую очередь смотрите на поля:
type— тип записи, напримерSYSCALLилиPATH.msg=audit(...)— timestamp и идентификатор события. По нему видно, какие строки относятся к одному действию.auid— audit user id, то есть исходный пользователь сессии. Часто это важнее, чем текущий uid после sudo.uid,euid,gid— реальные и эффективные идентификаторы процесса.comm— короткое имя команды.exe— путь к исполняемому файлу процесса.name— файл или каталог, которого коснулось событие.key— ваш ключ правила.
Например, если auid указывает на администратора, exe — на /usr/bin/vim, а name — на /etc/nginx/sites-enabled/example.conf, это похоже на ручное редактирование конфига. Если auid отсутствует или равен системному значению, exe показывает /usr/bin/rsync, а событие попало в окно деплоя, это может быть нормальный релиз. Если же exe — неожиданный процесс, а файл появился в upload-каталоге, нужно разбираться глубже.

Отчёты aureport: быстрый обзор без чтения audit.log вручную
ausearch удобен для расследования конкретного события, а aureport — для сводки. Он помогает быстро понять, какие ключи срабатывали чаще всего и какие файлы менялись.
sudo aureport -k -i
sudo aureport -f -i
sudo aureport -x -i
Ключ -k показывает отчёт по audit keys, -f — по файлам, -x — по исполняемым файлам. Для периода добавляйте --start и --end:
sudo aureport -k -i --start today
sudo aureport -f -i --start yesterday --end today
На практике удобно держать короткий набор команд для утренней проверки после ночных деплоев или подозрительных алертов. Например: сначала отчёт по ключам, затем поиск по самому активному ключу через ausearch, затем проверка конкретного файла через -f.
Настройка ротации и лимитов audit.log
Auditd пишет отдельный лог, обычно /var/log/audit/audit.log. Его ротация управляется не обычным logrotate-файлом Nginx, а параметрами /etc/audit/auditd.conf. На небольшой VDS важно проверить лимиты до включения правил на /var/www.
sudo grep -E 'max_log_file|num_logs|space_left|admin_space_left|disk_full_action' /etc/audit/auditd.conf
Полезные параметры:
max_log_file— размер одного audit.log в мегабайтах.num_logs— сколько старых файлов хранить.max_log_file_action— что делать при достижении лимита, часто используетсяROTATE.space_leftиadmin_space_left— пороги свободного места.disk_full_action— действие при заполнении диска.
Не ставьте бесконечную ретенцию на маленьком диске. Лучше хранить разумный локальный период и вывозить логи централизованно, если у вас есть отдельная система логирования. При этом учитывайте, что audit-логи могут содержать имена файлов, аргументы команд и другие чувствительные технические данные. Доступ к ним должен быть ограничен.
После изменения auditd.conf примените настройки. На части систем auditd защищён от обычного restart, поэтому безопаснее использовать штатный reload или service-команду, если она доступна.
sudo systemctl reload auditd
sudo service auditd reload
Если reload не поддерживается, запланируйте перезапуск в окно обслуживания. Не делайте рискованные операции с auditd одновременно с изменением firewall или SSH-доступа.
Как уменьшить шум от /var/www
Каталог /var/www редко бывает однородным. В нём могут лежать код, кеш, пользовательские загрузки, временные файлы, symlink на текущий релиз и несколько старых релизов. Одно правило на весь каталог удобно для старта, но не всегда подходит для постоянной эксплуатации.
Несколько практичных подходов:
- Аудировать не весь
/var/www, а конкретный production-путь:/var/www/example.com/currentили/var/www/example.com/public. - Не включать аудит на каталоги кеша, если приложение постоянно пишет туда файлы.
- Отдельно отслеживать конфигурацию и код, а пользовательские загрузки проверять другим инструментом: антивирусным сканированием, WAF-логами, контрольными задачами.
- Использовать разные ключи для разных сайтов, если на VDS несколько проектов.
- Согласовать правила с деплоем: события во время релиза нормальны, события ночью вне релиза — повод проверить.
Если у вас atomic deploy через symlink, auditd может вести себя не так, как ожидается, потому что watch ставится на конкретный путь и его разрешение в файловой системе. Для важных правил проверяйте реальный путь:
readlink -f /var/www/example.com/current
Иногда лучше аудировать каталог релизов или публичный каталог внутри текущего релиза, а не сам symlink. После изменения схемы деплоя обязательно повторите тест: создать файл, изменить права, удалить файл и убедиться, что ausearch видит событие.
Расширенные правила для критичных частей /etc
Если базовый аудит Nginx и PHP-FPM работает стабильно, можно добавить точечные правила для системных файлов, которые часто влияют на безопасность веб-сервера. Не обязательно аудировать весь /etc. Часто достаточно нескольких директорий и файлов.
# SSH and sudo
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/sudoers -p wa -k sudoers_changes
-w /etc/sudoers.d -p wa -k sudoers_changes
# Systemd units and timers
-w /etc/systemd/system -p wa -k systemd_units
# Cron jobs
-w /etc/crontab -p wa -k cron_changes
-w /etc/cron.d -p wa -k cron_changes
-w /etc/cron.daily -p wa -k cron_changes
Почему это важно для веб-стека? Инцидент не всегда начинается с изменения nginx.conf. Иногда добавляют systemd unit для закрепления, меняют cron, правят sudoers или ослабляют sshd-настройки. Auditd помогает увидеть эти изменения рядом с событиями в /var/www. Для отдельного контроля интерактивных входов пригодится инструкция про уведомления о SSH-входах через PAM и journald.
Типовой сценарий расследования
Представим ситуацию: мониторинг сообщил о подозрительном PHP-файле в /var/www/example.com/public/uploads. Сначала ищем события по файлу:
sudo ausearch -f /var/www/example.com/public/uploads/cache.php -i
Если файл уже удалён или имя неизвестно, смотрим ключ по веб-корню за период:
sudo ausearch -k webroot_changes -ts today -i
Затем проверяем, были ли попытки запуска из веб-корня:
sudo ausearch -k web_exec_from_webroot -ts today -i
После этого полезно посмотреть сводку по исполняемым файлам:
sudo aureport -x -i --start today
Если рядом по времени были изменения конфигов, проверяем Nginx и PHP-FPM:
sudo ausearch -k nginx_config -ts today -i
sudo ausearch -k phpfpm_config -ts today -i
Такой порядок экономит время. Вы не читаете весь audit.log, а идёте от конкретного артефакта к процессу, пользователю и соседним изменениям. Дальше уже подключаются бэкапы, Git-история, логи веб-сервера, access/error logs, журналы деплоя и проверка прав. Если расследование связано с переносом сайта, полезно свериться с чек-листом миграции сайта без простоя: он помогает отделить штатные изменения от неожиданных.
Частые проблемы и быстрые проверки
Правила не срабатывают
Проверьте, загружены ли они вообще:
sudo auditctl -l
sudo auditctl -s
Убедитесь, что путь существует и вы тестируете именно его. Для symlink-путей проверьте readlink -f. Также проверьте, что действие подходит под права правила: -p wa ловит запись и атрибуты, но не чтение.
Слишком много событий
Сузьте путь. Вместо /var/www используйте каталог конкретного сайта. Уберите кеши и временные каталоги из области аудита архитектурно: перенесите их за пределы отслеживаемого дерева или аудируйте только более важный подкаталог. Проверьте отчёт:
sudo aureport -k -i --start today
sudo aureport -f -i --start today
audit.log быстро растёт
Проверьте auditd.conf, активные ключи и самые шумные файлы. Если правило на /var/www фиксирует каждую запись кеша, это проблема правила, а не ротации. Ротация нужна, но она не должна маскировать ошибочную настройку.
В событии непонятный пользователь
Смотрите не только uid, но и auid. После sudo текущий uid может быть root, а auid сохранит исходного пользователя сессии. Для системных процессов auid может быть unset, тогда важнее exe, comm, unit в journald и соседние события.
Минимальный чек-лист внедрения на VDS
- Установить auditd и проверить
auditctl -s. - Добавить отдельный файл
/etc/audit/rules.d/50-web-audit.rules. - Начать с Nginx и PHP-FPM, затем осторожно добавить
/var/www. - Заменить uid в execve-правиле на пользователя вашего PHP-FPM pool.
- Загрузить правила через
augenrules --load. - Проверить тестовыми изменениями и поиском через
ausearch. - Посмотреть шум через
aureport -k -iиaureport -f -i. - Настроить лимиты
auditd.confи контролировать свободное место. - Документировать ключи правил, чтобы дежурный администратор понимал, что искать.
Итоги
Auditd на Linux VDS особенно полезен там, где веб-сервер обслуживает важный проект, а изменения должны быть объяснимы. Для Nginx и PHP-FPM достаточно начать с аудита конфигурационных каталогов и аккуратного контроля /var/www. Команда auditctl помогает проверить активные правила, ausearch — найти конкретные события, а aureport — быстро увидеть общую картину.
Самое важное — не превращать auditd в сборщик всего подряд. Хороший аудит отвечает на конкретные вопросы: кто изменил /etc/nginx, когда поменяли pool PHP-FPM, какой процесс создал файл в /var/www, были ли запуски из веб-корня. Такой набор правил даёт практичную пользу, не перегружает VDS и помогает быстрее разбирать инциденты и неожиданные изменения.


