Linux 基础体系 · 第 75/85 篇。示例面向现代主流 Linux 发行版;发行版差异、权限和生产风险会明确说明。
Linux auditd 审计:规则、事件、性能、检索和合规留存
auditd 是 Linux Audit 子系统的用户态守护进程。它接收内核产生的审计记录,将记录写入本地日志,或转发给其他插件。它解决的是“内核观察到了哪些安全相关行为,以及这些行为由谁、以什么身份、从哪里发起”的问题,而不是普通应用日志的统一收集器。
Linux 审计通常由以下组件组成:
- 内核 Audit 子系统:在系统调用、身份变化、权限检查、SELinux 决策等路径上生成审计记录。
auditd:从内核审计队列读取记录,并写入/var/log/audit/audit.log等文件。auditctl:查看和临时修改内核中的规则。augenrules:将/etc/audit/rules.d/*.rules合并后加载。ausearch:按时间、用户、事件类型、规则 key 等条件检索。aureport:生成登录、认证、系统调用、失败事件等汇总报告。- audisp 插件:将审计记录发送到其他处理程序,例如远程审计接收端。
不同发行版的包名和服务管理方式可能不同。RHEL、Rocky Linux、AlmaLinux、Fedora 通常使用 audit 或 auditd 包;Debian、Ubuntu 常见包名为 auditd。配置路径也可能由发行版打包策略决定,但 /etc/audit/auditd.conf 和 /etc/audit/rules.d/ 是现代主流发行版中最常见的布局。
一、审计数据流:从系统调用到日志文件
一个简化的数据流如下:
flowchart LR
P[进程] --> K[内核安全/系统调用路径]
K --> M[规则匹配]
M -->|匹配| Q[内核审计队列]
M -->|不匹配| X[不生成该规则事件]
Q --> A[auditd]
A --> L[/var/log/audit/audit.log]
A --> D[auディisp 插件]
L --> S[ausearch/aureport]
D --> R[远程接收或 SIEM]
实际路径中的关键状态如下:
- 进程执行系统调用,例如
openat()、execve()、setuid()。 - 内核根据已加载的审计规则判断是否需要记录。
- 如果需要记录,内核创建一个或多个审计记录,并放入审计队列。
auditd从队列读取记录,按照auditd.conf中的策略写入文件。ausearch和aureport读取文件并按事件进行解析。- 如果配置了 audisp 插件,记录还可能被转发到远端系统。
因此,auditd 停止运行并不等于内核完全停止产生审计事件。内核可能继续向队列写入,直到队列满;队列满后的行为由 failure、backlog_limit 和速率限制等配置共同决定。反过来,auditd 正常运行也不意味着所有安全行为都被审计:没有匹配规则的行为不会自动产生完整事件。
审计链路可以抽象为:
其中任一环节失败,都可能造成审计缺口。特别是“规则没有匹配”和“事件产生后丢失”是两种不同问题,排查时不能混为一谈。
Linux 内核是否启用了 Audit 支持,可先检查:
grep CONFIG_AUDIT /boot/config-$(uname -r)
常见结果类似:
CONFIG_AUDIT=y
CONFIG_AUDITSYSCALL=y
如果内核没有相关能力,安装 auditd 也不能补充内核事件。现代发行版通常默认启用,但定制内核、容器宿主机和极简系统不能假设这一点。
二、审计规则:审计什么、在什么条件下审计
1. 一条规则本质上是一个匹配谓词
一条系统调用审计规则可以理解为一个谓词:
其中:
action表示匹配后执行什么动作,常见为always或never。list表示规则挂在哪类内核审计列表,常见为exit。arch表示系统调用 ABI 架构,例如b64或b32。syscall表示系统调用名称,例如execve、openat。filters表示用户、路径、退出码、成功状态等附加条件。
只有当这些条件同时满足时,规则才会生成事件。例如:
-a always,exit -F arch=b64 -S execve,execveat \
-F auid>=1000 -F auid!=4294967295 -k user-command
它的含义不是“记录所有命令”,而是:
- 只匹配 64 位系统调用;
- 只关注
execve和execveat; - 只记录审计登录身份
auid大于等于 1000 的进程; - 排除尚未建立登录身份的进程;
- 给生成的事件附加
user-command这个 key。
这里的 auid 与当前有效用户 uid 不同。uid 可能因为 sudo、su 或 setuid 程序发生变化;auid 通常表示最初建立该会话的审计身份,用于回答“哪个登录用户最终发起了这个行为”。这也是审计中区分“当前权限身份”和“责任主体”的基础。
2. 规则来源与生命周期
临时查看当前内核规则:
sudo auditctl -l
查看审计状态:
sudo auditctl -s
典型字段包括:
enabled 1
failure 1
pid 1234
rate_limit 0
backlog_limit 8192
lost 0
backlog 0
这些字段分别表示:
enabled:审计是否启用;某些系统还会显示锁定状态。failure:规则或日志链路失败时的处理模式。pid:当前auditd进程号。rate_limit:每秒允许的事件数量上限,0通常表示不限速。backlog_limit:内核审计队列容量。lost:内核已经丢弃的事件数量。backlog:当前排队等待用户态读取的事件数量。
生产系统不应只执行 auditctl -l 就认为规则持久化了。直接用 auditctl 加载的规则通常只影响当前运行状态,重启后可能消失。持久化配置通常放在:
/etc/audit/rules.d/10-base.rules
/etc/audit/rules.d/50-custom.rules
然后由 augenrules 合并和加载:
sudo augenrules --check
sudo augenrules --load
sudo auditctl -l
不同发行版对服务重载的封装不同。修改规则后,应以本机发行版的 auditd 文档为准,不要在生产环境中盲目执行 systemctl restart auditd;某些系统会限制直接重启,重启还可能制造审计空窗。
如果规则文件最后包含:
-e 2
则表示将审计配置锁定为不可变状态。锁定后,通常只能通过重启加载新规则。这是防止运行中的特权进程修改审计策略的机制,但也会增加变更成本,因此必须确保规则经过验证,并把该行放在规则文件最后。
3. 常见规则类型
监视文件或目录
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/sudoers -p wa -k privilege-policy
-w /etc/sudoers.d/ -p wa -k privilege-policy
-w /etc/ssh/sshd_config -p wa -k ssh-config
-p 权限掩码常见含义为:
r:读取w:写入x:执行a:属性变化,例如权限、属主、时间戳变化
例如 -p wa 表示关注内容写入和元数据变化。
-w 是传统 watch 语法,兼容性较好,但在现代内核和 audit 工具中,系统调用规则配合 -F path= 或 -F dir= 往往更容易表达复杂过滤条件。目录监视还要考虑递归范围、挂载边界和发行版实现差异,不能把一个大型目录树直接当成低成本规则。
监视身份与权限变化
-a always,exit -F arch=b64 \
-S setuid,setgid,setreuid,setregid,setresuid,setresgid \
-k identity-change
-a always,exit -F arch=b64 \
-S capset \
-k capability-change
这些规则关注进程身份或 Linux capabilities 的变化。它们能够辅助发现提权行为,但不能代替 SELinux/AppArmor 的访问控制,也不能仅凭一次 setuid 事件判断“提权成功”。必须继续查看对应的 exit 值、进程、父进程和后续行为。
监视模块加载
-a always,exit -F arch=b64 \
-S init_module,finit_module,delete_module \
-F auid>=1000 -F auid!=4294967295 \
-k kernel-module
该规则只覆盖列出的系统调用和 64 位 ABI。系统中如果允许 32 位程序运行,还需要评估是否添加对应的 arch=b32 规则;不能简单复制所有规则,否则可能因为系统调用名称在不同 ABI 下不存在而导致加载失败或结果不符合预期。
监视命令执行
-a always,exit -F arch=b64 \
-S execve,execveat \
-F auid>=1000 -F auid!=4294967295 \
-k user-command
该规则常用于追踪交互式用户执行的程序,但它的成本可能很高。execve 触发频繁时,包管理器、构建系统、脚本解释器和服务启动过程会产生大量事件。它还不能记录 shell 中“没有启动新程序”的内建命令,例如:
cd /tmp
export A=1
umask 027
因此,execve 审计记录的是进程执行,不是完整的 shell 命令历史。PROCTITLE 和 EXECVE 记录也可能受参数长度、编码和内核实现影响,不能等价替代终端录制或应用级审计。
4. 架构条件不能省略
在 x86-64 主机上,常见系统调用架构是 b64。如果规则不指定架构,或者只覆盖一个 ABI,可能遗漏 32 位兼容程序。
可以查看机器架构:
uname -m
也可以观察已有事件中的:
arch=c000003e
arch 字段通常以十六进制表示;c000003e 常见于 x86-64。这里的日志字段不是配置文件中的 b64 字符串,两者是同一类架构信息的不同表达。
规则验证必须检查加载结果,而不是只看配置文件:
sudo augenrules --load
sudo auditctl -l
sudo auditctl -s
如果加载失败,应查看 auditd 或内核日志。常见原因包括:
- 系统调用名称在当前架构中不存在;
- 规则字段拼写错误;
- 试图修改已经由
-e 2锁定的配置; - 规则文件合并顺序导致行为与预期不同;
- 发行版使用了不同版本的
auditctl语法。
三、事件模型:一行日志不等于一个事件
1. 事件与记录的区别
Linux Audit 中,一个事件通常由同一时间戳和序列号关联的多条记录组成。例如:
type=SYSCALL msg=audit(1710000000.123:456): ...
type=EXECVE msg=audit(1710000000.123:456): ...
type=PROCTITLE msg=audit(1710000000.123:456): ...
type=CWD msg=audit(1710000000.123:456): ...
其中:
audit(时间戳:序列号)
括号中的 456 是该审计事件的序列号。多个记录共享同一个序列号,表示它们属于同一个事件上下文。
SYSCALL 常包含:
syscall:系统调用编号;success:系统调用是否成功;exit:返回值或错误码;a0至a3:系统调用原始参数;items:关联路径项数量;auid:审计登录身份;uid、euid、suid、fsuid:不同用户身份;pid、ppid:进程和父进程;comm:进程短名称;exe:可执行文件路径;subj:SELinux 等安全上下文;key:命中的规则 key。
PATH 记录说明系统调用涉及的文件路径,CWD 记录当时的工作目录,EXECVE 记录执行参数,PROCTITLE 记录进程标题。并不是每种系统调用都生成这些附属记录,具体字段取决于事件类型和内核路径。
例如,文件路径可能同时出现在 PATH 中,而实际成功与否应优先查看 SYSCALL 的:
success=yes
exit=0
如果看到:
success=no
exit=-13
通常表示系统调用失败,-13 对应 EACCES。失败事件仍然有审计价值,因为它能显示探测、越权尝试或错误配置;不能只收集成功事件。
2. 一次文件操作的推导示例
假设用户执行:
sudo sh -c 'echo test >> /etc/example.conf'
可能发生如下过程:
- shell 或重定向逻辑调用
openat()。 - 内核根据
/etc/example.conf的规则进行匹配。 - 如果文件以追加写方式打开,规则
-p w可能命中。 - 内核记录执行该系统调用的进程身份、路径和返回值。
auditd将相关SYSCALL、PATH等记录写入日志。ausearch -k some-key根据规则 key 找到整个事件。
但不能从这条事件直接推出“文件最终内容一定是 test”。系统调用可能成功打开文件后,后续写入失败;也可能另一个进程马上覆盖内容。审计事件描述的是被观测到的内核行为,不自动提供业务语义上的最终状态。
3. 身份字段的实际含义
一个事件可能出现:
auid=1001 uid=0 euid=0
合理解释是:用户 1001 登录后,通过 sudo 以 root 有效身份执行了操作。若只查看 uid=0,只能知道当时进程拥有 root 身份,无法知道最初责任用户。
但是 auid 并非任何场景都可靠:
- 系统启动阶段的服务可能没有登录审计身份;
- 由内核、守护进程或容器运行时创建的进程可能出现未设置值;
- 容器内外的 UID、PID 和审计上下文不能直接等同;
- 身份切换后,
uid和auid的变化规律取决于 PAM、登录方式和程序行为。
因此,事件分析通常要同时看 auid、uid、euid、ses、pid、ppid、exe、addr 和时间窗口。
四、登录、SSH 与审计关联
SSH 登录通常涉及多个日志来源:
sshd的认证和会话日志;- PAM 生成的审计事件;
- 内核记录的进程、文件和身份变化;
- systemd journal 或 rsyslog 转发后的文本日志。
常见审计事件类型包括:
USER_AUTH:认证行为;USER_LOGIN:登录结果;USER_START、USER_END:用户会话开始和结束;CRED_ACQ、CRED_REFR:凭据获取或刷新;USER_CMD:某些用户态组件记录的命令行为。
具体事件是否产生,取决于 OpenSSH、PAM 模块、发行版配置和审计规则,不能保证每台机器都有完全相同的事件集合。OpenSSH 的认证、会话和日志行为应结合本机 sshd_config 以及 OpenSSH 手册确认,不能仅凭 auditd 日志推断所有认证细节。
查询最近的登录相关事件:
sudo ausearch -m USER_LOGIN,USER_AUTH,USER_START \
--start recent --interpret
查询 SSH 服务日志:
sudo journalctl -u sshd --since "1 hour ago"
Debian/Ubuntu 上服务名通常为 ssh:
sudo journalctl -u ssh --since "1 hour ago"
关联分析时,可按以下路径核对:
- 在 SSH 日志中找到时间、远端地址、用户名和认证结果。
- 在审计事件中检查
addr、auid、ses和uid。 - 在同一时间窗口查找
execve、权限变化和敏感文件访问。 - 使用
pid、ppid和exe判断后续行为是否由sshd、shell 或sudo派生。 - 结合 NTP/chrony 状态确认不同主机的时间可比较。
这类关联不是“按用户名 grep 一下”。同一个用户名可以有多个并发会话,pid 会变化,auid 可能相同,时间戳还可能因时钟偏差造成误判。
五、检索与报告:按事件解析,而不是直接 grep
1. ausearch 的基本用法
查询某个规则 key:
sudo ausearch -k ssh-config --interpret
查询某个时间范围:
sudo ausearch --start today --end now --interpret
查询某个用户的事件:
sudo ausearch -ua 1001 --start recent --interpret
查询失败的系统调用:
sudo ausearch --success no --start recent --interpret
查询具体事件类型:
sudo ausearch -m SYSCALL,PATH --start recent --interpret
--interpret 会把 UID、系统调用号、网络地址等字段转换为更容易阅读的形式。机器处理时应慎用解释后的文本,优先保留原始字段:
sudo ausearch -k user-command --raw --start today
直接使用:
grep "key=user-command" /var/log/audit/audit.log
有几个问题:
- 一个事件由多条记录组成,grep 可能只拿到其中一行;
- 日志可能已经轮转;
- 字段可能十六进制编码;
- 时间、UID 和事件类型的解析容易出错;
- 多行记录之间需要依据
audit(timestamp:serial)重新分组。
所以,grep 适合快速定位,不适合作为审计事件解析器。
2. aureport 适合汇总,不适合替代原始证据
常见报告:
sudo aureport --auth
sudo aureport --login
sudo aureport --failed
sudo aureport --syscall
例如:
sudo aureport --failed --summary
它能回答“失败认证有多少”“哪些系统调用失败较多”等汇总问题,但汇总会丢失很多上下文。调查单个事件时,应回到 ausearch 的原始记录,保留完整事件组和日志文件来源。
3. 完整检索算例
假设目标是调查“用户 alice 在今天是否修改了 SSH 配置,并随后执行了什么程序”。
第一步,找到配置修改事件:
sudo ausearch -k ssh-config --start today --end now --interpret
从结果中记录:
audit序列号;auid;uid和euid;pid、ppid;exe;success和exit;PATH中的实际路径;ses和addr。
第二步,按 auid 和会话继续查找命令执行:
sudo ausearch -ua 1001 --start today --end now -k user-command --interpret
第三步,核对修改是否成功:
type=SYSCALL ... success=yes exit=0 auid=1001 uid=0 euid=0 ...
type=PATH ... name="/etc/ssh/sshd_config" nametype=NORMAL ...
如果只看到:
success=no exit=-13
则说明该次系统调用被拒绝,不能写成“配置已被修改”。
第四步,检查 SSH 服务是否重新加载:
sudo journalctl -u sshd --since today
配置文件的写入、sshd -t 校验和服务重载是三个不同事实。审计记录只能证明被审计的系统调用;要判断服务是否采用新配置,还必须检查服务日志和当前服务状态。
六、性能:审计开销来自哪里
审计性能不能用一个固定百分比概括。开销取决于:
- 系统调用频率;
- 规则数量;
- 每条规则中的字段过滤;
- 是否进行路径解析;
- 是否记录
execve参数; - 事件生成速率;
auditd写盘速度;- 磁盘轮转和远程转发;
- 突发流量与内核队列大小。
可以把单个事件从内核到磁盘的平均处理时间粗略表示为:
其中:
- :规则匹配和路径判断时间;
- :生成
SYSCALL、PATH等记录的时间; - :等待用户态读取的时间;
- :写入本地文件或插件的时间。
这不是内核的性能保证,只是定位瓶颈的模型。系统调用越频繁,单位时间的事件数越多:
其中 是第 类行为的发生速率, 是该行为命中审计规则的比例。当事件到达速率长期高于 auditd 的处理速率时,队列会增长;若持续增长到 backlog_limit,就会触发丢失或失败策略。
查看当前压力:
sudo auditctl -s
重点观察:
backlog是否长期接近backlog_limit;lost是否增长;- 日志写盘是否出现延迟;
auditd是否报告磁盘或插件错误。
1. 高成本规则的典型来源
以下规则可能产生很大流量:
-a always,exit -F arch=b64 -S all -k everything
或对整个根文件系统进行广泛路径监视:
-w / -p wa -k all-files
它们的问题不是“语法错误”,而是匹配范围过大。构建机、数据库服务器、容器宿主机和高并发 Web 服务器可能迅速产生海量事件,导致:
- CPU 消耗上升;
- 日志磁盘写满;
- 关键事件被普通噪声淹没;
- 内核队列堆积;
- 在严格失败模式下阻塞或停止业务系统调用。
更合理的做法是围绕风险边界选择规则,例如身份数据库、SSH 配置、sudo 策略、内核模块、时间配置、关键服务二进制和特定管理操作,而不是默认记录所有系统调用。
2. 队列与失败策略
auditd.conf 中常见配置包括:
log_file = /var/log/audit/audit.log
log_format = RAW
flush = incremental_async
freq = 50
num_logs = 10
max_log_file = 100
max_log_file_action = ROTATE
space_left = 100
space_left_action = SYSLOG
admin_space_left = 50
admin_space_left_action = SUSPEND
disk_full_action = SUSPEND
disk_error_action = SUSPEND
这些参数的确切默认值和可用动作依发行版版本而异,修改前应查看:
man auditd.conf
flush=incremental_async 一般降低同步写盘开销,但在机器突然掉电时可能损失尚未落盘的数据。更强的刷新策略通常提高持久性成本;这是可靠性与性能的取舍,不存在对所有场景都正确的值。
内核失败策略常见为:
0:静默处理;1:打印内核消息;2:触发 panic。
生产环境使用 failure=2 需要非常谨慎。它提高了“审计不可用时不继续运行”的强度,却可能把磁盘满、审计守护进程故障或规则错误转化为主机不可用。合规要求若没有明确规定,不能只因“更严格”就直接启用。
可以在低风险环境模拟压力并观察:
for i in $(seq 1 1000); do true; done
sudo auditctl -s
这个例子只有在已启用 execve 等规则时才会显著产生事件,而且 true 可能由 shell 内建命令或外部程序实现,结果随 shell 和发行版变化。测试结果不能直接当作生产吞吐基准。
七、日志轮转、磁盘治理与合规留存
1. 轮转不是留存策略
max_log_file 控制单个审计日志文件大小,num_logs 控制轮转文件数量;但这些参数只描述本地文件生命周期。例如:
max_log_file = 100
num_logs = 30
max_log_file_action = ROTATE
如果单位是 MiB,这个配置最多只保留约 3 GiB 的轮转文件,实际还受已有文件、文件系统、压缩策略和发行版行为影响。它不能证明“保留 180 天”,因为每天事件量可能不同。
基于容量的留存时间可以估算为:
其中:
- 是用于审计日志的可用空间;
- 是每天产生的日志量;
- 是估计留存天数。
如果每天流量有突发,应该使用高分位而不是平均值。例如平均每天 2 GiB、峰值每天 10 GiB 的主机,用平均值计算出来的留存期在事故期间可能迅速失真。
2. 磁盘满的故障路径
审计日志写满磁盘时,可能经历:
space_left触发提醒动作;- 低于
admin_space_left后触发管理员级动作; - 文件系统无空间后触发
disk_full_action; - 如果失败策略严格,部分系统调用可能失败,甚至主机停机;
- 如果策略宽松,业务继续运行,但审计证据出现缺口。
因此,必须为 /var/log/audit 单独规划容量或文件系统,并监控:
df -h /var/log/audit
df -ih /var/log/audit
sudo auditctl -s
sudo journalctl -u auditd --since "1 hour ago"
同时要注意 inode 耗尽、远程挂载不可用、权限被错误修改和日志轮转失败等非容量问题。
3. 合规留存需要额外的存储与完整性控制
auditd 的本地日志默认是普通文件。它不会自动提供不可抵赖性、WORM 保留、跨主机备份或完整的篡改证明。要满足具体合规要求,通常还需要:
- 将事件实时或准实时发送到独立日志接收端;
- 接收端使用访问隔离、对象锁定或 WORM 存储;
- 限制审计管理员对历史日志的删除和修改权限;
- 对归档文件计算哈希并保存哈希清单;
- 使用可信时间同步;
- 记录轮转、上传、失败和恢复状态;
- 定期进行恢复演练和随机抽样校验;
- 明确保留期限、法定保全和删除规则。
远程转发不能自动等价于加密传输或不可篡改。使用 audisp-remote 时,应确认本机版本支持的传输方式、目标端认证和网络保护措施;必要时通过受控网络、VPN 或符合组织要求的加密通道保护链路。
审计日志本身含有用户名、路径、命令参数、网络地址和安全上下文,属于敏感数据。集中留存时还要控制谁能够检索,避免“为了合规保留日志”却扩大了凭据、令牌或业务参数的暴露面。
八、与 journald、rsyslog 和 SELinux 的边界
1. auditd 与 journald
journald 主要管理 systemd 服务日志、内核日志和结构化字段;auditd 主要消费 Linux Audit 事件。二者可能在同一主机共存,但不是同一个数据源。
例如:
journalctl -k
适合查看内核日志,而:
ausearch -m SYSCALL --start recent
用于查询审计系统调用事件。
某些发行版会把审计相关消息同时呈现在 journal 中,但不能因为 journalctl 能看到某条消息,就认为它保留了完整的 Audit 事件组。合规取证时应保留原始审计日志或经过验证的结构化归档。
2. rsyslog 与 auditd
rsyslog 擅长接收和转发 syslog 消息;auditd 负责 Audit 记录。把 /var/log/audit/audit.log 当作普通文本文件交给 rsyslog 读取,可能破坏事件分组、重复转发或造成文件竞争。应优先使用 auditd/audisp 提供的插件链路,再在接收端统一进入日志平台。
3. SELinux/AppArmor 与 auditd
SELinux 和 AppArmor 是访问控制机制;auditd 是记录和检索机制。以 SELinux 为例,一次访问可能:
- 被 SELinux 拒绝并产生 AVC 审计记录;
- 被传统 Unix 权限拒绝并产生系统调用失败记录;
- 权限允许但没有匹配 Audit 规则,因此没有对应文件审计事件。
因此:
auditd不能替代 SELinux/AppArmor;- SELinux 允许不代表业务允许;
- 没有 Audit 事件不代表行为没有发生;
- AVC 日志也不能代替对关键文件和身份变化的审计。
排查权限问题时,通常要并行查看:
sudo ausearch -m AVC --start recent --interpret
sudo ausearch --success no --start recent --interpret
sudo journalctl -k --since "10 minutes ago"
具体命令是否可用取决于系统是否启用了 SELinux;AppArmor 系统应使用对应的内核日志和工具。
九、生产变更流程与故障恢复
审计规则属于安全控制面,修改时应区分“验证规则”和“启用规则”。
推荐在测试主机执行:
sudo cp -a /etc/audit/rules.d /etc/audit/rules.d.backup.$(date +%F-%H%M%S)
sudo augenrules --check
sudo augenrules --load
sudo auditctl -l
sudo auditctl -s
然后用实际动作验证:
sudo touch /etc/example.conf
sudo chmod 640 /etc/example.conf
sudo ausearch -k example-key --start recent --interpret
如果规则是:
-w /etc/example.conf -p wa -k example-key
预期应看到与 touch 和 chmod 相关的事件,但具体记录数量、PATH 类型和系统调用名称会随内核与工具版本变化。验证重点是:
- 事件是否产生;
- 事件中的路径是否正确;
- 成功和失败状态是否符合实际;
auid、uid、exe是否可解释;lost是否保持不变;- 日志轮转和远程发送是否正常。
如果新规则导致事件量暴涨,恢复步骤应包括:
- 停止继续扩大规则范围;
- 从备份恢复规则文件;
- 若没有
-e 2,重新加载经过验证的旧规则; - 若已经锁定,按变更设计重启到已知规则版本;
- 检查
auditctl -s中lost、backlog和失败状态; - 标记受影响的审计时间窗口,不要把不完整日志当成完整证据。
lost=0 只说明内核报告的丢失计数当前为零,不能证明过去没有发生规则遗漏,也不能证明远程接收端已经成功持久化。完整性判断必须结合规则版本、主机状态、轮转记录、远程接收确认和存储校验。
十、常见误解与边界
误解一:安装 auditd 后自动审计所有行为
错误。没有匹配规则的普通文件读取、进程执行或权限变化,不会自动形成你所需要的完整事件。发行版可能预置一部分规则,但其范围和目的不同,必须用 auditctl -l 确认。
误解二:审计记录了“用户输入的每条命令”
错误。execve 记录程序执行;shell 内建命令、别名展开、函数逻辑和部分解释器内部行为不会因此完整出现。命令参数还可能被截断、编码或由解释器统一呈现。
误解三:uid=0 就表示 root 直接登录
错误。sudo、setuid 程序和服务都可能产生 uid=0。应结合 auid、ses、exe、ppid、SSH/PAM 日志判断责任链。
误解四:没有事件就代表没有访问
错误。可能是规则未覆盖、使用了未匹配的 ABI、事件在其他主机或容器边界产生,也可能在队列、磁盘或远程传输阶段丢失。
误解五:把规则写得越宽越安全
错误。过宽规则会增加性能压力、日志噪声和故障概率,反而降低调查质量。规则应从威胁模型和合规控制项推导:先确定需要证明的事实,再选择能最小成本证明该事实的系统调用、路径和身份过滤条件。
审计的核心价值不是“日志越多越好”,而是让关键安全事实可验证:
- 谁建立了会话;
- 谁以什么权限执行了什么程序;
- 哪个敏感对象被访问或修改;
- 操作成功还是失败;
- 事件是否完整到达了受控存储;
- 在规定期限内能否检索并证明日志未被悄然删除或修改。
当规则、事件关联、性能保护、检索方法和独立留存同时成立时,auditd 才能从“主机上有一个日志文件”变成可用于安全响应和合规取证的审计控制。
系列导航与关联阅读
- 系列入口:Linux 完整学习路线:从内核与文件系统到网络、性能和生产运维
- 上一篇:AppArmor 完整基础:Profile、Mode、规则、日志和服务加固
- 下一篇:Linux 资源限制:ulimit、RLIMIT、systemd Limit、文件句柄和进程数
- 延伸:Linux 主机安全加固:最小化、SELinux/AppArmor、审计与漏洞治理
- 延伸:Linux 日志体系:journald、rsyslog、轮转、结构化采集和磁盘治理
官方资料
本文依据 Linux 内核、systemd 与主流发行版官方文档重新梳理;正文与实验由 WR BLOG 编写。

评论
0 条讨论