На работе у меня есть пара серверов с видеозаписями и рекламными материалами, свалка из 20Тб больших файлов, многие из которых используются не чаще чем раз в 5 лет. Получилось так что часть старых видеозаписей оказалась частично поломанной, как куски по 5 минут вырвали, сложно сказать из-за чего это получилось, но неприятный факт остается фактом. Был и бекап правда на нем записаны уже поломанные файлы.
Первая мысль написать быстренько скрипт использующий md5sum или md5deep, который раз в месяц будет проверяющий хеши от всех файлов и отправлять результаты на почту. Чуть позже я наткнулся на AIDE (Advanced Intrusion Detection Environment) изначально предназначенный для проверки целостности всей системы. Главная прелесть AIDE – возможность для каждой отдельной директории настроить большое количество контролируемых парметров, дата, размер, разрешения, хеш-алгоритмы для файлов.
1. Конфигурационный файл
Ставим программу
[root@smb02 ~]# yum install aide
И переходим к конфигурационному файлу /etc/aide.conf
@@define DBDIR /var/lib/aide @@define LOGDIR /var/log/aide # database - файл БД папок и файлов, из которого будут читаться данные при # выполнении check и update database=file:@@{DBDIR}/aide.db.gz # database_out - файл БД папок и файлов, в который будут писаться данные при # выполнении init и update. Если задать в database и database_out один и тоже файл # то процедура update объединяющая в себе check и init работать не будет. database_out=file:@@{DBDIR}/aide.db.new.gz gzip_dbout=yes # Упаковать базу данных gzip-ом verbose=5 # Подробность вывода report_url=file:@@{LOGDIR}/aide.log # Выводить логи в файл report_url=stdout # Выводить логи в stdout
Проверяемые параметры
#p: разрешения на файл #i: дескриптор inode #n: количество ссылок #u: пользователь #g: группа #s: размер #b: количество блок #m: mtime - время последней модификации #a: atime - время последнего доступа #c: ctime - время последнего изменения атрибутов файла #S: check for growing size #acl: Access Control Lists #selinux SELinux security context #xattrs: Extended file attributes # Алгоритмы хеширования #md5: md5 checksum #sha1: sha1 checksum #sha256: sha256 checksum #sha512: sha512 checksum #rmd160: rmd160 checksum #tiger: tiger checksum #haval: haval checksum (MHASH only) #gost: gost checksum (MHASH only) #crc32: crc32 checksum (MHASH only) #whirlpool: whirlpool checksum (MHASH only) # Группы разрешений #R: p+i+n+u+g+s+m+c+acl+selinux+xattrs+md5 #L: p+i+n+u+g+acl+selinux+xattrs #E: Empty group #>: Growing logfile p+u+g+i+n+S+acl+selinux+xattrs
Вышеперечисленных параметры мы можем группировать и создавать на основе их свои правила
# Проверяем все-возможные разрешения и атрибуты, считаем хеш-суммы rmd160 и sha256 NORMAL = R+rmd160+sha256 # Проверяем разрешения, дескриптор inode, ссылки, пользователя, группу, список доступа, # контекст selinux, расширенные атрибуты DIR = p+i+n+u+g+acl+selinux+xattrs # Проверяем все-возможные разрешения и атрибуты, считаем хеш-сумму sha256 LSPP = R+sha256
Папкам которые мы хотим контролировать нужно назначить соответствующие параметры или правила.
# содержимое каталога /boot обрабоатываем правилом NORMAL /boot NORMAL # в папке /etc/cron.d проверяем разрешения, размер и хеш-сумму sha1 /etc/cron.d/ p+s+sha1 # исключаем папку src !/usr/src # исключаем файлы оканчивающиеся на ~ !/etc/.*~ # Везде где встречается директория lost+found обрабатываем правилом DIR =/lost\+found DIR
Для моей задачи вполне достаточно проверять у файлов пользователя, группу, размер, хеш-сумму sha1, ну и на всякий случай md5 (что бы уж наверняка).
/data u+g+s+mtime+sha1+md5
Проверяем конфиг, если команда не выведет ошибок – значит все правильно.
[root@smb02 ~]# aide --config-check
2. Использование
Инициализируем базу данных. Инициализировать – это значит прочитать все файлы согласно правил и записать информацию о них в базу данных из параметра database_out.
[root@smb02 ~]# aide --init
Копируем файл aide.db.new.gz в aide.db.gz, соответствующий параметру database. Затем запускаем проверку, которая опять читает все файлы согласно параметров и сравнивает с параметрами в aide.db.gz, в случае расхождения она выведет подробную информацию о найденных различиях.
[root@smb02 ~]# cp /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz [root@smb02 ~]# aide --check
Следующая функция – это обновление, она считывает все файлы согласно правил и записывает результат в aide.db.new.gz, и параллельно сравнивает с данными из aide.db.gz. Именно из-за нее приходится держать два файла с базами, но это намного эффективнее нежели чем использовать init и check, особенно с учетом необходимости считать хеш-суммы для большого количества файлов.
[root@smb02 ~]# aide --update
3. Автоматизация
Итак, AIDE конечно классная утилита, но весь процесс проверки нужно автоматизировать, так что бы можно было его спокойно повесить на cron и получать по почте сообщения. Ниже представлен небольшой скриптик, который все это делает и дополнительно еще оставляет историю БД, что тоже очень полезно если вдруг потребуется сравнить что-же все-таки изменилось за прошедшие 5 лет.
#!/bin/bash # Скрипт для запуска AIDE и отправки отчетов по почте # Имя файла для логов logfile=/var/log/aide/`date +%d.%m.%Y-%H:%M`.log # Почта для отчетов admin_mail=admin@alsigned.ru # Параметры базы данных такие как в /etc/aide.conf databasedir=/var/lib/aide database=aide.db.gz database_out=aide.db.new.gz # Проверяем не защен ли уже один из экземляров скипта runfile=/var/run/aide_run [ -e $runfile ] && { echo "AIDE process already running."; exit 0; } touch $runfile if [ ! -e $databasedir/$database ]; then # Если файла базы для чтения не существует запускаем инциализацию /usr/sbin/aide --init --report=file://$logfile > /dev/null # Отправляем сообщение на почту mail -s "AIDE database initialized on `hostname`" "$admin_mail" < $logfile else # Запускаем обновление /usr/sbin/aide --update --report=file://$logfile > /dev/null # Отправляем логи на почту mail -s "AIDE working result from `hostname`" "$admin_mail" < $logfile fi # У AIDE есть очень полезная функция - сравнивать между собой две базы # поэтому на всякий случай сохраняем историю баз по дате cp $databasedir/$database_out $databasedir/aide.db.`date +%d.%m.%Y-%H:%M`.gz # Переименовываем новую базу в базу для чтения mv $databasedir/$database_out $databasedir/$database rm $runfile
На этом все.
2 Коммент. : “Проверка целостности файлов”
Не обязательно. В Debian, например, подсчёт MD5 всех файлов происходит на уровне менеджера пакетов. На другой машине тоже можно из пакетов достать список контрольных сумм.
Совершенно с тобой согласен, менеджер пакетов в большинстве дистрибутивов Linux делает автоматическую проверку целостности. Но в данной статье речь идет немного о другом. Предположим ситуацию есть файл Х весом 2Гб, который один раз положили и менять не собираются, с этого файла делается бекап с периодичностью раз в неделю, бекапы же месячной давности затираются. Так вот если в один прекрасный момент этот файл будет поврежден, то можно гарантировать что через месяц восстановить его будет невозможно. Соответственно что бы этого избежать мы периодически проверяем хеш-суммы файлов.