Linux AppArmor 配置与应用

4次阅读

apparmor策略需手动加载才生效,配置文件位于/etc/apparmor.d/,须用apparmor_parser或aa-enforce显式解析;路径匹配以绝对路径为准,不支持递归通配符**(旧内核),且依赖进程工作目录;初始profile推荐aa-genprof交互式生成,aa-autodep仅作补充;加载后拒绝无日志时应检查audit设置、profile模式及进程名匹配。

Linux AppArmor 配置与应用

AppArmor 配置文件写在哪、怎么加载

AppArmor 的策略不是写在 /etc/apparmor.d/ 下就自动生效的——必须显式加载。默认策略文件放在 /etc/apparmor.d/,但只有被 aa-enforceapparmor_parser 解析后才起作用。

常见错误:改完 /etc/apparmor.d/usr.bin.firefox 就以为限制生效了,结果进程照样读任意文件。其实得手动加载:

  • sudo apparmor_parser -r /etc/apparmor.d/usr.bin.firefox(重载单个)
  • sudo aa-enforce /etc/apparmor.d/usr.bin.firefox(等价,但更语义化)
  • 加载失败时,apparmor_parser 会报错,比如 Invalid profile: 'deny /tmp/**' — missing comma or unexpected Token,注意末尾逗号和空格

profile 中 path 规则为什么总不匹配

路径匹配是 AppArmor 最容易出错的部分:它不支持通配符递归(** 只在部分新版内核中有限支持),且路径以进程当前 working Directory 为基准,不是绝对路径的“字面意思”。

典型场景:你想限制 /opt/myapp/bin/myserver 不能写 /var/log/myapp/,但 profile 写成 /var/log/myapp/** rw, 却没生效——因为该进程实际 chdir 到了 /opt/myapp,而 AppArmor 默认用相对路径解析(除非加 abstraction 或显式声明 /var/log/myapp/** 为绝对路径)。

  • 始终用绝对路径开头,如 /var/log/myapp/** rw,,不要省略 /
  • ** 不等于 shell 的 glob:它只匹配多级子目录,不跨挂载点,也不展开符号链接
  • 检查是否被 abstraction 覆盖:运行 aa-status 看 profile 是否处于 enforce 模式,且对应进程名是否列在 “processes” 下

如何快速生成初始 profile(aa-genprof vs aa-autodep)

aa-genprof 是交互式学习模式,适合首次为未知程序建模;aa-autodep 是静态依赖扫描,只看二进制 ldd 和硬编码路径,漏掉运行时打开的文件(比如日志路径、配置目录)。

真实使用中,90% 的失败 profile 都源于只跑了一次 aa-autodep 就上线。它生成的规则太窄,连 /proc/sys/kernel/osrelease 这种系统信息读取都会被拦。

  • 新服务首次配 policy,必须用 sudo aa-genprof /usr/bin/myapp,然后实际操作一遍所有功能(启动、读配置、写日志、调 API)
  • aa-autodep 只适合补漏或快速初稿,例如:aa-autodep /usr/local/bin/backup.sh 得到基础路径后,再进 aa-genprof 补日志和临时文件规则
  • 注意 aa-genprof 会把 ptracesignal 等权限也记下来,生产环境要人工删掉不必要的 capability

profile 加载后进程仍被拒绝,但 dmesg 没日志

AppArmor 拒绝行为默认只记到内核 ring buffer,不一定进 dmesg 或 syslog——尤其当 audit=1 未启用,或日志级别被过滤时。

最直接的办法是开 audit 日志并实时抓:运行 sudo dmesg -w | grep -i apparmor,再触发一次被拒操作(比如 touch 一个受限路径)。如果还看不到,说明可能根本没命中 profile——进程名不匹配,或者 profile 处于 complain 模式。

  • 确认 profile 名和进程名一致:ps aux | grep myapp 看实际命令路径,profile 文件名应为 /etc/apparmor.d/usr.bin.myapp 或通过 #include 引入
  • 检查当前模式:sudo aa-status | grep myapp,输出里是 enforce 还是 complain
  • 若用 systemd 启动,确保 service 文件没加 ProtectSystem=strict 等干扰 AppArmor 的选项,二者叠加可能导致策略冲突

AppArmor 的坑不在语法多难,而在路径解析逻辑、加载时机、和 audit 日志可见性这三点上。调一个 profile 花两小时,往往一小时在找为什么没生效,而不是写规则本身。

text=ZqhQzanResources