Inotify – Monitorizando modificaciones en el sistema de ficheros

Normalmente cuando queremos monitorizar cambios en un sistema de ficheros siempre solemos encontrar como punto de referencia programas como AIDE, Tripwire o incluso RkHunter. En líneas generales estas utilidades tienen el objetivo de garantizar la integridad de determinados ficheros en nuestro sistema. Para ello realizan un hash de los mismos, estableciendo así una línea base que sirva como punto de comparación frente a análisis posteriores. Si cambia el hash de un fichero, deducimos entonces que ese fichero ha sido modificado y nuestro programa debería notificárnoslo tras realizar un análisis de integridad.

Por otro lado, tenemos otro método sencillo para tal menester que consiste en hacer uso del subsistema del kernel llamado inotify. De su página man leemos:

También en su página de manual tenéis algunos detalles acerca del funcionamiento de la API para los más curiosos.

En Debian, para utilizar inotify de una forma sencilla contamos con las utilidades inotifywait y inotifywatch del paquete inotify-tools:

apt-get install inotify-tools

Estas utilidades son interfaces para hacer uso de la API de inotify de una forma sencilla. Vamos a ver para qué sirve cada una.

Inotifywait: notificación de operaciones sobre ficheros

Con inotifywait podemos monitorizar cambios en un fichero particular o un directorio, incluso recursivamente sobre los subdirectorios que se encuentren por debajo.

En una terminal ponemos a monitorizar inotifywait sobre el directorio /home/bob/sandbox/

[bob@debianbob]:~$ inotifywait -m /home/bob/sandbox/
Setting up watches.
Watches established.

Con la opción -m especificamos que inotifywait monitorice el directorio indefinidamente, ya que por defecto deja de ejecutarse tras recibir un único evento.

En otra terminal, realizo lo siguiente:

[bob@debianbob]:~/sandbox$ echo "test1" > /home/bob/sandbox/test1
[bob@debianbob]:~/sandbox$ echo "test1" > /home/bob/sandbox/test1
[bob@debianbob]:~/sandbox$ echo "test2" > /home/bob/sandbox/test2
[bob@debianbob]:~/sandbox$ echo "test3" > /home/bob/sandbox/test3

En la terminal donde está lanzado inotifywait recibo los siguientes eventos:

[bob@debianbob]:~$ inotifywait -m /home/bob/sandbox/
Setting up watches.
Watches established.
/home/bob/sandbox/ CREATE test1
/home/bob/sandbox/ OPEN test1
/home/bob/sandbox/ MODIFY test1
/home/bob/sandbox/ CLOSE_WRITE,CLOSE test1
/home/bob/sandbox/ MODIFY test1
/home/bob/sandbox/ OPEN test1
/home/bob/sandbox/ MODIFY test1
/home/bob/sandbox/ CLOSE_WRITE,CLOSE test1
/home/bob/sandbox/ CREATE test2
/home/bob/sandbox/ OPEN test2
/home/bob/sandbox/ MODIFY test2
/home/bob/sandbox/ CLOSE_WRITE,CLOSE test2
/home/bob/sandbox/ CREATE test3
/home/bob/sandbox/ OPEN test3
/home/bob/sandbox/ MODIFY test3
/home/bob/sandbox/ CLOSE_WRITE,CLOSE test3

Como vemos, se están monitorizando todas las operaciones realizadas sobre los ficheros del directorio /home/bob/sandbox/

Ahora imaginemos que queremos monitorizar las modificaciones únicamente en el directorio /home/bob/sandbox/ y que se nos notifique al correo en caso de cualquier cambio:

inotifywait -r -m /home/bob/sandbox/ -e modify | while read path action file;do
	echo "Change detected date $(date) in ${path} action ${action} in file ${file}" \
    | mail -s "Modification detected, check ASAP" emailsample@example.com;
done

En caso de modificación de por ejemplo el fichero test3, recibiríamos en nuestro correo un email con el título “Modification detected, check ASAP” y el mensaje:

Change detected date Sun Aug 21 19:40:14 CEST 2016 in /home/bob/sandbox/ action MODIFY in file test3

Si vamos a utilizar notificaciones por correo es muy importante que filtremos los eventos que queremos monitorizar con el parámetro -e, ya que se enviará un correo por cada evento recibido lo que puede generar una cantidad de tráfico indeseada.

Otra opción de uso sería guardar los eventos en un fichero de histórico en vez de mandar correo. Esto no nos permitirá responder de una forma tan rápida como anteriormente, pero puede servir en función de las necesidades que tengamos:

inotifywait -r -m /home/bob/sandbox/ -e modify | while read path action file;do
	echo "Change detected date $(date) in ${path} action ${action} in file ${file}" > inotifyhistory
done

En cualquier caso, las posibilidades que ofrece inotifywait son numerosas. Para ver una lista de los eventos que puede se pueden monitorizar podéis ir a la página de manual correspondiente con un man inotifywait.

Inotifywatch: recolección de estadísticas

Por otro lado, inotifywatch nos permite monitorizar estadísticas de operaciones sobre un directorio o fichero. Por ejemplo, monitoricemos /home/bob/sandbox en una consola:

bob@debianbob]:~$ inotifywatch /home/bob/sandbox/
Establishing watches...
Finished establishing watches, now collecting statistics.

Ahora, desde otra terminal lanzo lo siguiente en el directorio /home/bob/sandbox/

[bob@debianbob]:~$ echo "file1" > /home/bob/sandbox/file1
[bob@debianbob]:~$ echo "file1" > /home/bob/sandbox/file1
[bob@debianbob]:~$ echo "file2" > /home/bob/sandbox/file2
[bob@debianbob]:~$ echo "file3" > /home/bob/sandbox/file3
[bob@debianbob]:~$ rm /home/bob/sandbox/file3

Volvemos a la consola en la que habíamos lanzado inotifywatch y presionamos Ctrl+C. Veremos lo siguiente:

total  access  modify  close_write  close_nowrite  open  create  delete  filename
37     8       5       4            6              10    3       1       /home/bob/sandbox/

Vemos que inotifywatch ha capturado cada unos de los eventos y los ha contabilizado para mostrarnos estadísticas de las operaciones realizadas.

Como en el caso de inotifywait, podemos filtrar los eventos a monitorizar con el parámetro -e. También podéis echar un vistazo a todas sus opciones en la página man correspondiente.