auditd 系统调用审计实战:规则语法、ausearch/aureport 检索与关键文件告警闭环

auditd 系统调用审计实战:规则语法、ausearch/aureport 检索与关键文件告警闭环

服务器被入侵后,站长最常问的一句话往往是「它是什么时候进来的、动了哪些文件」。如果你的机器上没有开启审计,这个问题就只能靠猜。Lynis、OpenSCAP 这类工具做的是「基线体检」,告诉你配置哪里不够硬;而 auditd 做的是「运行时记录」,它把内核里发生的系统调用、文件访问、权限变更一条条落到磁盘,事后可以像调监控录像一样回放。两者互补,但真正能在事故里救命的,是 auditd。这篇文章从零讲清楚 auditd 的规则语法、日志检索方式,以及如何用一条可维护的告警链路把它真正用起来,而不是装完就吃灰。

一、auditd 到底在记录什么

Linux 内核里有一个 audit 子系统,每当发生「可审计事件」时,内核会生成一条 audit record。用户态守护进程 auditd 通过 netlink 从内核接收这些记录,写进 /var/log/audit/audit.log。默认情况下,auditd 只会记录少量事件(比如登录、SELinux/AppArmor 拒绝),要真正有价值,必须自己下规则。

一条规则由三部分决定它能匹配什么:

  • 过滤键(filter):task、exit、user、exclude、filesystem。最常用的是 exit(按系统调用返回值和 syscall 匹配)与 filesystem(按文件路径监控)。
  • 动作(action):-a 是「总是记录(always)」,-a never 是排除,-w 是简写形式的文件监控(watch)。
  • 字段匹配:-F 后面跟字段=条件,如 -F arch=b64 -F perm=wa -F path=/etc/passwd。

规则文件放在 /etc/audit/rules.d/ 下,以 .rules 结尾,由 augenrules 合并成 /etc/audit/audit.rules。这样分文件维护、互不覆盖,是推荐做法。

二、安装与最小可用配置

# Debian/Ubuntu
apt-get install -y auditd audispd-plugins

# RHEL/CentOS
yum install -y audit audispd-plugins

# 主配置
vi /etc/audit/auditd.conf

# 关键参数建议:
#   max_log_file = 100        单文件 100MB
#   num_logs = 10             滚动保留 10 个
#   max_log_file_action = keep_logs   不要把旧日志删掉,轮转即可
#   space_left_action = email 空间告急发邮件
#   admin_space_left_action = single  极端情况下切单用户保日志
#   flush = incremental
#   freq = 50                 折衷性能与丢日志风险

最忌讳的配置是 space_left_action = rotate 配上很小的 num_logs,一旦有进程疯狂产生 audit 事件(比如遍历百万文件被监控的目录),旧日志会被快速覆盖,事故现场直接丢失。保留策略上「宁占空间不丢记录」,磁盘紧张就调大分区或单独挂一个 /var/log/audit。

三、三类最有价值的规则

1. 关键身份与权限文件监控

# /etc/audit/rules.d/10-identity.rules
-w /etc/passwd   -p wa -k identity
-w /etc/shadow   -p wa -k identity
-w /etc/group    -p wa -k identity
-w /etc/gshadow  -p wa -k identity
-w /etc/sudoers  -p wa -k sudoers
-w /etc/sudoers.d -p wa -k sudoers

-p wa 表示监听 write 与 attribute(属性变更,如 chmod/chown)。-k 是自定义键名,之后 ausearch -k identity 就能一键捞出所有相关记录。任何新用户被添加、密码被改、sudoers 被改,都会留痕——这是入侵检测里性价比最高的一组规则。

2. 提权与命令执行监控

# /etc/audit/rules.d/20-exec.rules
# 记录 execve 系统调用(命令执行)
-a always,exit -F arch=b64 -S execve -k exec
-a always,exit -F arch=b32 -S execve -k exec

# 单独盯 root 下发的提权
-a always,exit -F arch=b64 -F euid=0 -S setuid -S setgid -k privilege

注意:记录全部 execve 会让日志暴涨,生产机上建议要么不整体开启,要么配合 au 的 rate limit(-r 100 表示每秒最多 100 条)。更好的做法是只监控指定目录下的可执行文件,或只监控 /tmp、/dev/shm 这类常被投毒的位置。

3. 敏感目录变更与提权后门监控

# 监控 /tmp 与 /dev/shm 下的可执行写入(挖矿、反弹 shell 常在此落马)
-w /tmp -p x -k tmp_exec
-w /dev/shm -p x -k shm_exec

# 监控 SSH 配置和 authorized_keys 被改写
-w /root/.ssh -p wa -k ssh_keys
-w /etc/ssh/sshd_config -p wa -k sshd_config

# 监控内核模块加载(rootkit 常用)
-a always,exit -F arch=b64 -S init_module -S finit_module -k modules

四、加载规则与验证

# 语法自检(不生效,只检查)
augenrules --check

# 合并并加载
augenrules --load

# 查看当前生效的规则
auditctl -l

# 看每条规则的命中计数(第 2 列是 hits)
auditctl -s

加载后可以故意触发一次,验证规则生效:

touch /tmp/probe
chmod +x /tmp/probe
ausearch -k tmp_exec -ts recent

如果 ausearch 返回 <no matches>,先确认 auditctl -s 里 enabled 是否为 1、规则是否真的在列表里,再看 /var/log/audit/audit.log 是否有写入。常见坑是把规则写进了 /etc/audit/audit.rules 却忘了 augenrules 会覆盖它,改动应当只放 rules.d/。

五、ausearch 与 aureport:把日志变成答案

audit.log 的原始格式很像天书,ausearch 与 aureport 是把它翻译成人话的两把钥匙。

# 按 key 检索
ausearch -k identity -i

# 按时间范围
ausearch -k exec -ts today -i
ausearch -k ssh_keys -ts 2026-10-01 00:00:00 -te 2026-10-02 00:00:00 -i

# 按可执行文件名过滤
ausearch -x /usr/bin/curl -i

# 只看失败的系统调用
ausearch -m syscall -sv no -i

# 关联某进程 PID 的全部行为
ausearch -p 4312 -i

-i 参数会把 uid 解析成用户名、把 syscall 号解析成名字、把时间戳解析成可读时间,几乎必加。当你已经锁定了一个可疑 PID,用 ausearch -p <pid> -i 就能把这个进程从启动到销毁的行为串起来,这是应急取证里最常用的一步。

# 各类事件统计汇总
aureport --summary
aureport -au            # 认证事件汇总(成功/失败登录)
aureport -l --failed    # 失败登录明细
aureport -f -i          # 文件访问报告
aureport -x -i          # 可执行文件报告
aureport -k             # 按 key 统计命中次数(查规则是否被触发)

aureport -au --failed 是排查暴力破解的利器:如果看到同一个 IP 或同一个用户短时间内几十上百条失败登录,基本可以确认是爆破。结合 fail2ban 或 sshd 的 MaxAuthTries 就能形成闭环。

六、构建一个可维护的告警闭环

audit 记录再多,没人看等于零。有两种轻量做法,不需要上一整套 SIEM。

做法 A:audisp-syslog + rsyslog 关键字告警

# /etc/audit/plugins.d/syslog.conf
active = yes
direction = out
path = builtin_syslog
type = builtin
args = LOG_INFO
format = string

开启后 audit 事件会同步进 syslog,再用 rsyslog 的 :msg, contains, "key=identity" 规则分流到单独文件,配合 ommail 或一个 webhook 脚本发通知。

做法 B:定时脚本扫描 + 增量告警

#!/usr/bin/env bash
# /usr/local/bin/audit-watch.sh
# 每 5 分钟扫一次最近的关键事件,有新记录就告警
STATE=/var/lib/audit-watch.last
touch "$STATE"

for KEY in identity sudoers ssh_keys modules; do
  # 只在时间窗口内检索
  HITS=$(ausearch -k "$KEY" -ts recent -i 2>/dev/null | grep -c '^time->' || true)
  if [ "$HITS" -gt 0 ]; then
    ausearch -k "$KEY" -ts recent -i | mail -s "[AUDIT] $KEY touched on $(hostname)" admin@example.com
  fi
done

如果不想依赖 mail,也可以把结果 POST 到企业微信/钉钉/飞书的机器人 webhook。关键是「有事件才发」,否则告警会变成噪音,最后被你静音。

七、性能与运维的几个现实建议

  • 先小范围再铺开:先上身份文件 + SSH + 内核模块这三组低噪音规则,观察一周再逐步加 execve 这类高噪音规则。
  • 注意 32/64 位架构:x86_64 上要同时写 -F arch=b64 和 -F arch=b32 两条,否则 32 位程序(不少老工具、静态编译的挖矿程序)会绕过监控。
  • immutable 模式:规则稳定后可在 /etc/audit/rules.d/99-finalize.rules 里写 -e 2,此时 audit 配置被冻结,连 root 都不能在运行期删规则,防止攻击者反手关日志。代价是改规则必须重启才生效。
  • 日志独立分区:/var/log/audit 单独挂载,避免被其它日志的磁盘写满连带波及。
  • 备份审计日志到远端:本地日志可被 root 清除,用 rsyslog 或 audisp-remote 把记录实时推到另一台机器,才真正具备「不可篡改」的取证价值。

八、一次典型的应急流程

假设你发现服务器有异常外连,可以按下面的顺序跑:

# 1. 先看最近失败登录,判断是否被爆破进来
aureport -au --failed -ts today

# 2. 看最近被改过的身份/权限文件
ausearch -k identity -ts today -i
ausearch -k sudoers  -ts today -i

# 3. 看有没有新的内核模块或可疑可执行
ausearch -k modules -ts this-week -i
ausearch -k tmp_exec -ts this-week -i

# 4. 锁定可疑 PID,回放全部行为
ausearch -p <pid> -i

# 5. 汇总统计,确认时间线
aureport --start today --summary

这套流程的价值在于:它给你的是时间线和证据,而不是「感觉被入侵了」。有了时间线,才能判断该回滚备份还是清理加固,才能对外说清楚影响范围。

九、排错与降噪的实战要点

规则上线后最常见的两个问题,一是「什么都没记录」,二是「记录太多没人看」。前者通常是规则没加载(augenrules --load 忘跑、或者把规则写进了会被覆盖的 audit.rules),也可能是内核 audit 被 disabled(auditctl -s 显示 enabled 0,多半是启动参数里带了 audit=0)。后者则是规则颗粒度太粗,比如整体开启 execve 却没做 rate limit,几分钟就能把日志写爆。

降噪的核心思路是「只关心异常,不关心正常」。举例来说,你并不需要知道每个进程都在读什么文件,只需要知道谁在往外连、谁在改身份文件、谁在加载内核模块。把这几个「高信号」事件单独成组,日志量立刻降下两个数量级,人也愿意看了。对于确实需要保留的全量数据,可以按天切割、冷存到对象存储,用 ausearch 在需要时按 key 拉回来。

另一个容易被忽视的点是审计日志本身要防篡改。攻击者拿到 root 后第一反应往往是清理足迹,rm /var/log/audit/audit.log 或把 auditctl -e 0 关掉。除了前面提过的 immutable 模式和远程转发,还可以用 chattr +a /var/log/audit/audit.log 给日志加上 append-only 属性(内核支持时有效),让它只能追加不能被删除或截断。多道防线叠加,才能保证「出事后现场还在」。

十、小结

auditd 不是装完就完事的工具,它的价值取决于规则设计得对不对、日志有没有被安全地留存下来。身份文件监控 + SSH 密钥监控 + 内核模块监控是必开的三组低噪音高价值规则;ausearch 负责事后精确定位,aureport 负责全局统计;再用一个简单的增量脚本把「有事件才告警」的闭环搭起来。做到这三步,你的服务器就从「黑盒」变成了「有监控录像的房间」,出事时不再两眼一抹黑。

Last modification:October 10th, 2026 at 10:25 pm

Leave a Comment