Хочете миттєво дізнаватися про зміну файлів у системі — від підозрілих модифікацій у /etc до раптового зникнення скриптів у /usr/local/bin? Тоді вам сподобається зв'язка inotifywait + bash + systemd. Вона легка, швидка і не потребує складних агентів. У цій статті я покажу, як увімкнути миттєвий аудит змін, отримувати лог у journald та файл, а також за бажанням — настільні сповіщення. 🔎⚡

Як це працює

Ми використаємо inotify (ядровий механізм подій файлової системи). У ролі спостерігача — inotifywait, який генерує події створення/видалення/переміщення/зміни. Простий bash скрипт збере метадані (власник, права, SHA-256), запише все у лог і, за бажанням, покаже нотифікацію. Запуск і контроль процесу реалізує systemd — це надійніше, ніж звичайний cron, хоча для періодичних задач згодиться і розділ cron та systemd timers. Такий підхід — про легкий Linux моніторинг і здорову автоматизацію задач.

Основний How-to

Крок 1. Встановіть необхідні пакунки

Вам потрібні inotify-tools. Опційно — libnotify-bin для графічних сповіщень.

# Debian/Ubuntu
sudo apt update && sudo apt install -y inotify-tools libnotify-bin

# Fedora
sudo dnf install -y inotify-tools libnotify

# Arch/Manjaro
sudo pacman -S --noconfirm inotify-tools libnotify

Крок 2. Підготуйте конфіг (список шляхів і винятків)

Ми стежитимемо за чутливими каталогами. Почніть із малого, щоб не потонути в подіях:

sudo sh -c 'cat >/etc/instant-audit.env' <<'EOF'
# Шляхи для моніторингу (пробіл-роздільник)
WATCH_PATHS="/etc /usr/local/bin $HOME/.ssh"
# Регулярка для виключень (тимчасові/приховані файли, кеші)
EXCLUDE_RE="(^|/)\.(cache|git|svn)|\.swp$|~$"
# Куди писати додатковий лог
LOG_FILE="/var/log/instant-audit.log"
EOF

Пояснення: /etc — системні конфіги; /usr/local/bin — ваші скрипти; ~/.ssh — ключі. За потреби додайте /var/www або інші каталоги застосунків.

Крок 3. Створіть скрипт-наглядача

Скрипт слухає події, логуватиме в journald (через logger) та у файл, обчислюватиме sha256 для змінених файлів і за потреби надсилатиме нотифікацію.

sudo tee /usr/local/bin/instant-audit.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail

WATCH_PATHS="${WATCH_PATHS:-/etc /usr/local/bin $HOME/.ssh}"
EXCLUDE_RE="${EXCLUDE_RE:-(^|/)\.(cache|git|svn)|\.swp$|~$}"
LOG_FILE="${LOG_FILE:-/var/log/instant-audit.log}"

command -v inotifywait >/dev/null || { echo "inotifywait not found"; exit 1; }

mkdir -p "$(dirname "$LOG_FILE")"
touch "$LOG_FILE" && chmod 0600 "$LOG_FILE"

TS() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
log() {
  local msg="$1"
  printf "%s %s\n" "$(TS)" "$msg" | tee -a "$LOG_FILE" | logger -t instant-audit
}
notify_gui() {
  if command -v notify-send >/dev/null && [ -n "${DISPLAY:-}" ]; then
    notify-send -u critical "Instant audit" "$1"
  fi
}

inotifywait -m -r \
  -e create,delete,modify,move,attrib \
  --format '%T|%w|%f|%e' --timefmt '%Y-%m-%d %H:%M:%S' \
  --exclude "$EXCLUDE_RE" $WATCH_PATHS | \
while IFS='|' read -r t dir file ev; do
  path="${dir}${file}"
  perm=""; hash="NA"
  if [ -e "$path" ] && [ ! -d "$path" ]; then
    perm="$(stat -c '%U:%G %a' "$path" 2>/dev/null || true)"
    hash="$(sha256sum "$path" 2>/dev/null | awk '{print $1}')"
  fi
  log "event=$ev path=$path perms=$perm sha256=$hash"
  case "$ev" in
    *DELETE*|*MOVED_FROM*) notify_gui "Removed: $path";;
    *CREATE*|*MOVED_TO*)   notify_gui "Created: $path";;
    *MODIFY*|*ATTRIB*)     notify_gui "Changed: $path";;
  esac
done
EOF

sudo chmod +x /usr/local/bin/instant-audit.sh

Зверніть увагу: inotify не показує користувача, який змінив файл. Для атрибуції особи краще підходить auditd (див. альтернативи нижче).

Крок 4. Описуємо і запускаємо сервіс systemd

sudo tee /etc/systemd/system/instant-audit.service >/dev/null <<'EOF'
[Unit]
Description=Instant file-change audit via inotifywait
After=network.target

[Service]
Type=simple
EnvironmentFile=-/etc/instant-audit.env
ExecStart=/usr/local/bin/instant-audit.sh
Restart=always
RestartSec=2s
# Потрібні права для читання системних каталогів
User=root
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now instant-audit.service

# Перевірка логів
journalctl -u instant-audit.service -f

Протестуйте події:

sudo touch /etc/test.audit
sudo chmod 600 /etc/test.audit
sudo rm -f /etc/test.audit

# Дивимося файл додаткового логу
sudo tail -f /var/log/instant-audit.log

Альтернативні способи

  • auditd (глибинний аудит із прив'язкою до користувача/процесу):
    sudo apt install -y auditd  # у Debian/Ubuntu
    sudo auditctl -w /etc -p wa -k etc-watch
    # Перегляд подій
    sudo ausearch -k etc-watch --start recent | sudo aureport -f -i
    Плюси: хто/чим змінив файл, SELinux-aware. Мінуси: складніше налаштовувати, більше шуму.
  • incron/fswatch: правило-подія-скрипт, зручно для окремих директорій. Мінус: менша гнучкість порівняно з нашим підходом + systemd.
  • AIDE/Tripwire: індексація контрольних сум і періодична перевірка (через cron). Це не миттєво, але добре як другий рубіж контролю цілісності.
  • systemd.path: зручно для конкретних файлів (наприклад, /etc/passwd), але не рекурсивно для великих дерев.
    # Приклад: спрацьовує, коли /etc/passwd змінено
    sudo tee /etc/systemd/system/passwd-watch.path >/dev/null <<'EOF'
    [Path]
    PathChanged=/etc/passwd
    [Install]
    WantedBy=multi-user.target
    EOF
    sudo tee /etc/systemd/system/passwd-watch.service >/dev/null <<'EOF'
    [Service]
    Type=oneshot
    ExecStart=/usr/bin/logger -t passwd-watch \
      "passwd modified at $(date -Is)"
    EOF
    sudo systemctl daemon-reload
    sudo systemctl enable --now passwd-watch.path

GUI-спосіб (сповіщення і перегляд логів)

Якщо ви працюєте з робочим столом, додайте сповіщення через notify-send (ми вже вбудували це в сценарій). Переконайтеся, що сервіс запускається у сеансі з DISPLAY, або запустіть окремий користувацький екземпляр. Для перегляду подій у графіці використовуйте Gnome Logs або KSystemLog — відкрийте журнал unit'а instant-audit.service і фільтруйте за тегом instant-audit.

FAQ

Чому я не бачу деяких подій або їх надто багато?

Можливо, вперлися у ліміт inotify. Збільшіть його і зробіть постійним:

echo fs.inotify.max_user_watches=1048576 | sudo tee /etc/sysctl.d/99-inotify.conf
sudo sysctl --system

Отримую Permission denied на системних каталогах

Запускайте сервіс від root або оберіть каталоги, доступні вашому користувачу. Альтернатива — перенести атрибуцію змін на auditd.

Як зменшити шум від тимчасових/IDE-файлів?

Розширте EXCLUDE_RE, наприклад:

sudo sed -i 's/\$"/|node_modules|vendor|\.tmp$"/' /etc/instant-audit.env
sudo systemctl restart instant-audit.service

Сервіс упав/завис

Перевіряйте журнал:

journalctl -u instant-audit.service -e
sudo systemctl restart instant-audit.service

Чи можна отримувати email?

Так. Додайте в скрипт виклик mailx у гілках notify_gui (потрібен mailutils/postfix), або використайте webhook на ваш SOC/Slack.

Навіщо ще згадувати cron та systemd timers?

Вони корисні для періодичних перевірок цілісності (AIDE), ротації логів чи health-check самого моніторингу, хоча миттєві події ми ловимо через systemd-сервіс та inotify.

Порада від Kernelka

Починайте з 1–2 ключових директорій і поступово розширюйте охоплення. Тримайте журнал у захищеному місці (права 600), а також експортуйте його в централізоване сховище логів — так злочинцю важче «замести сліди».

Підсумок

  • inotifywait + bash + systemd = легкий і швидкий миттєвий аудит змін.
  • Логи — у journald і в окремий файл, опційно — графічні сповіщення.
  • Налаштовуйте виключення і ліміти inotify, щоб уникнути шуму.
  • Для атрибуції «хто змінив» розгляньте auditd як доповнення.
  • Використовуйте cron та systemd timers для періодичних перевірок і ротації.

Нехай ваш Linux буде пильним, а ви — спокійними. Якщо що — пишіть у коментарях, допоможу розібратися з помилками та оптимізацією linux команд у вашому середовищі.