工作中,有时候我们需要知道某个文件是否被修改了, 被哪个程序修改了. Linux 下可以很方便地监控某个文件被修改的记录. 根据目的不同, Linux 下有不同的监视文件或文件夹的方案.
Table of Contents A. Auditd 安装 auditd 配置 audit 监视规则 检查文件操作记录 Systemtap 安装 Systemtap 获取文件信息 Systemtap 监控脚本 监控文件 inotifywait 安装 inotify-tools 监控 文件夹下的文件产生,修改,删除
A. Auditd
Auditd 可以很方便监控记录哪些程序和用户对指定文件(即使不存在)做的操作.
安装 auditd
一般发行版软件仓库里都会有 auditd 安装包. 如果默认没有安装,可以很方便地利用包管理器来安装
1 2 3 4 5 6 $ sudo dnf install -y audit $ sudo yum install -y audit $ sudo apt install -y audit
启动 audit 服务
1 $ sudo systemctl enable --now auditd
检查 audit 服务状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ sudo systemctl status auditd ● auditd.service - Security Auditing Service Loaded: loaded (/usr/lib/systemd/system/auditd.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2018-09-07 08:47:53 CST; 10min ago Docs: man:auditd(8) https://github.com/linux-audit/audit-documentation Process: 28126 ExecStartPost=/sbin/augenrules --load (code=exited, status=0/SUCCESS) Process: 28121 ExecStart=/sbin/auditd (code=exited, status=0/SUCCESS) Main PID: 28122 (auditd) Tasks: 5 (limit : 4915) Memory: 3.3M CGroup: /system.slice/auditd.service ├─28122 /sbin/auditd ├─28124 /sbin/audispd └─28127 /usr/sbin/sedispatch
这就表示服务正常.
配置 audit 监视规则
为了监视文件的访问操作, 需要在/etc/audit/rules.d/audit.rules
添加如下规则, 其中 perm
是要监控的操作, key
是在查寻时指定的关键字, path
是要监控的文件路径.
1 2 $ vi /etc/ audit/rules.d/ audit.rules -a always,exit -F path=/path/ to/file -F perm=warx -F key=keyword-for -filter-log
重启 audit 服务
1 2 $ sudo service auditd restart
检查 audit
规则.
1 2 $ sudo auditctl -l -a always,exit -F path=/path/to/file -F perm=warx -F key=keyword-for-filter-log
检查文件操作记录
假如我们监控 /root/test.txt
的操作, 规则是
1 -a always,exit -F path=/root/test.txt -F perm=warx -F key=test-filter
然后对其做一些操作
1 2 3 $ ls /root/test.txt $ cat /root/test.txt $ touch /root/test.txt
然后通过如下命令查询操作记录.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 $ ausearch -k test-filter time->Fri Sep 7 09:23:24 2018 type =PROCTITLE msg=audit(1536283404.017:39844): proctitle=63617400746573742E747874type =PATH msg=audit(1536283404.017:39844): item=0 name="test.txt" inode=1587579 dev=103:08 mode=0100644 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0type =CWD msg=audit(1536283404.017:39844): cwd="/root" type =SYSCALL msg=audit(1536283404.017:39844): arch=c000003e syscall=257 success=yes exit =3 a0=ffffff9c a1=7fff145999ed a2=0 a3=0 items=1 ppid=32477 pid=10767 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts4 ses=3 comm="cat" exe="/usr/bin/cat" key="test-filter" ---- time->Fri Sep 7 09:27:22 2018 type =PROCTITLE msg=audit(1536283642.307:40008): proctitle=6C73002D2D636F6C6F723D6175746Ftype =PATH msg=audit(1536283642.307:40008): item=0 name="test.txt" inode=1587579 dev=103:08 mode=0100644 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0type =CWD msg=audit(1536283642.307:40008): cwd="/root" type =SYSCALL msg=audit(1536283642.307:40008): arch=c000003e syscall=191 success=no exit =-61 a0=7ffcd0a58c40 a1=7f4b30ece210 a2=7ffcd0a58c00 a3=14 items=1 ppid=1617 pid=12314 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts6 ses=3 comm="ls" exe="/usr/bin/ls" key="test-filter" ---- time->Fri Sep 7 09:27:29 2018 type =PROCTITLE msg=audit(1536283649.775:40009): proctitle=746F75636800746573742E747874type =PATH msg=audit(1536283649.775:40009): item=1 name="test.txt" inode=1587579 dev=103:08 mode=0100644 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0type =PATH msg=audit(1536283649.775:40009): item=0 name="/root" inode=1569793 dev=103:08 mode=040550 ouid=0 ogid=0 rdev=00:00 nametype=PARENT cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0type =CWD msg=audit(1536283649.775:40009): cwd="/root" type =SYSCALL msg=audit(1536283649.775:40009): arch=c000003e syscall=257 success=yes exit =3 a0=ffffff9c a1=7fff075909e1 a2=941 a3=1b6 items=2 ppid=1617 pid=12367 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts6 ses=3 comm="touch" exe="/usr/bin/touch" key="test-filter"
我们可以看到都有 cat
, ls
, touch
在相应的时间对其做了什么操作. aureport
可以给出更直观的报告,
1 2 3 4 $ ausearch -k test_filter | aureport -f -i 33. 09/07/2018 09:56:23 test.txt getxattr no /usr/bin/ls amito 41596 34. 09/07/2018 09:56:26 test.txt openat yes /usr/bin/cat amito 41600 35. 09/07/2018 09:56:28 test.txt openat yes /usr/bin/touch amito 41607
Systemtap
systemtap
功能非常强大,可以监控系统调用, 也可检测文件的修改操作. 但是需要安装系统的 debug 模块. 可能需要在相应的 repo
中 设置 debug 为enabled=1
安装 Systemtap
1 2 3 4 $ sudo dnf install -y kernel-debuginfo kernel-debuginfo-common systemtap systemtap-client systemtap-runtime systemtap-devel $ sudo yum install -y kernel-debuginfo kernel-debuginfo-common systemtap systemtap-client systemtap-runtime systemtap-devel
获取文件信息
1 2 $ stat -c '%D %i' test.txt 10308 1587579
Systemtap 监控脚本
下面这个脚本可以监控文件的修改记录.将脚本保存为 inodewatch.stp
1 2 3 4 5 6 7 8 9 10 11 #! /usr/bin/env stap probe vfs.write, vfs.read { if (dev == MKDEV($1 ,$2 ) && ino == $3 ) printf ("%s(%d) %s 0x%x/%u\n" , execname(), pid(), ppfunc(), dev, ino) }
监控文件
1 $ sudo stap sudo stap inodewatch.stp 0x103 0x08 1587579
其中连个十六进制数字 0x103 0x08
是上面得到的文件设备ID 10308
. 现在对 test.txt
做一些操作.
1 2 vim test.txt cat test.txt
脚本会给出如下类似的信息
1 2 3 4 5 6 7 8 vim(22230) vfs_read 0x10300008/1587579 vim(22230) vfs_read 0x10300008/1587579 vim(22230) vfs_read 0x10300008/1587579 vim(22230) vfs_read 0x10300008/1587579 vim(22230) vfs_read 0x10300008/1587579 vim(22230) vfs_write 0x10300008/1587579 cat(22303) vfs_read 0x10300008/1587579 cat(22303) vfs_read 0x10300008/1587579
我们可以看到 vim
, cat
对test.txt
做了一些读写操作.
inotifywait
inotifywait
是 inotify-tools
里带的工具可以监控文件的修改建立等等.
1 2 3 $ sudo dnf install -y inotify-tools $ sudo apt install -y inotify-tools
监控 文件夹下的文件产生,修改,删除
1 2 3 4 5 $ inotifywait -m /path/to/watch -r -e create -e moved_to -e delete -e modify | while read path action file; do $ ... $ your action here $ ... $ done
比如, 在特定文件 test.txt
产生时,给特定邮箱发邮件, 并删除它
1 2 3 4 5 6 7 $ inotifywait -m /path -e create -e moved_to | while read path action file; do $ echo "The file '$file ' appeared in directory '$path ' via '$action '." $ if [[ $file == "test.txt" ]]; then $ echo "The file '$file ' appeared in directory '$path ' via '$action '. Deleting" |mutt -s "Deleting $file " your_email $ sudo rm -rf /path/test.txt $ fi $ done