На работе у меня есть пара серверов с видеозаписями и рекламными материалами, свалка из 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 Коммент. : “Проверка целостности файлов”

  1. Не обязательно. В Debian, например, подсчёт MD5 всех файлов происходит на уровне менеджера пакетов. На другой машине тоже можно из пакетов достать список контрольных сумм.

  2. Совершенно с тобой согласен, менеджер пакетов в большинстве дистрибутивов Linux делает автоматическую проверку целостности. Но в данной статье речь идет немного о другом. Предположим ситуацию есть файл Х весом 2Гб, который один раз положили и менять не собираются, с этого файла делается бекап с периодичностью раз в неделю, бекапы же месячной давности затираются. Так вот если в один прекрасный момент этот файл будет поврежден, то можно гарантировать что через месяц восстановить его будет невозможно. Соответственно что бы этого избежать мы периодически проверяем хеш-суммы файлов.

Оставить комментарий