Linux AppArmor 配置与安全策略

1次阅读

apparmor配置文件默认位于/etc/apparmor.d/,需按路径命名(斜杠换为点),加载后仅对新启动进程生效;用aa-status查看生效状态,apparmor_parser -r或systemctl restart apparmor重载。

Linux AppArmor 配置与安全策略

AppArmor 配置文件在哪?怎么确认它在生效

AppArmor 策略不是写完就自动起作用的,得先加载进内核、再让进程实际按策略跑起来。默认配置文件放在 /etc/apparmor.d/ 下,但注意:文件名必须和被保护程序的完整路径对应(比如 /usr/bin/firefox 对应 /etc/apparmor.d/usr.bin.firefox),中间斜杠要替换成点。

常见错误是改了文件却没 reload,或者 reload 了但进程没重启——策略只对新启动的进程生效。用 aa-status 能立刻看到当前哪些进程正在受保护、用了哪个 profile;如果某进程没列出来,要么没启用 profile,要么它根本没按 profile 启动(比如直接 /usr/bin/python3 script.py,而不是通过 systemd 或 wrapper 启动)。

  • sudo apparmor_parser -r /etc/apparmor.d/usr.bin.python3 重载单个 profile
  • sudo systemctl restart apparmor 重载全部(部分发行版不支持该 service)
  • 检查是否启用:cat /sys/module/apparmor/parameters/enabled 应输出 Y

profile 里 abstractioninclude 有什么区别

两者都用来复用规则,但语义和加载时机不同。abstraction 是 AppArmor 内置的一组通用权限集合(比如 abstraction/python 允许 Python 解释器读取标准库路径),它被设计为“可组合、无副作用”,多个 profile 可以安全 include 同一个 abstraction。

include 则是纯文本包含,类似 C 的 #include,不做任何解析或校验——如果 included 文件里写了 deny /etc/shadow r,,那就真 deny,不会因为上下文自动调整。容易踩的坑是:误把 include 当成 abstraction 复用,结果在多个 profile 里重复包含同一段规则,导致权限叠加出错(比如意外多开了网络访问)。

  • 优先用 abstraction:它们经过测试,适配主流发行版路径
  • include 适合放自定义的通用片段,比如公司内部日志路径规则,但要确保路径不冲突
  • 路径写法:abstraction 在 /usr/share/apparmor/abstractions/,include 默认从 /etc/apparmor.d/ 开始找相对路径

为什么 aa-logprof 生成的规则总不准

aa-logprof 依赖 dmesg 或 /var/log/audit/audit.log 里的拒绝日志(APPARMOR_DENIED),但它只能看到“被拦住的请求”,看不到“本该拦但没拦”的行为。所以它倾向于过度宽松:比如某程序偶尔读 /tmp/foo.sockaa-logprof 就会加一条 /tmp/** rw,,而不是更精确的 /tmp/foo.sock rw,

真实生产环境里,得手动收紧。关键是看日志里的 operation 字段(如 openconnect)、name(路径)、profile(当前用的 profile 名)和 requested_mask(想要的权限)。别直接信 aa-logprof 推荐的 /**,尤其对 /tmp/dev/proc 这类目录。

  • sudo aa-logprof -f /var/log/syslog 指定日志源(ubuntu 默认走 syslog)
  • 交互时选 2(Ask again)比直接 1(Add rule)更安全
  • 生成后务必用 aa-complain /path/to/profile 先切到 complain 模式观察几天,再切 enforce

systemd 服务怎么套 AppArmor profile

systemd 不会自动给服务进程套 profile,除非显式指定。最可靠的方式是在 service unit 文件里加 AppArmorProfile=(systemd v245+),比如:

[Service] AppArmorProfile=/etc/apparmor.d/usr.bin.mydaemon

老版本 systemd 或某些发行版(如 Ubuntu 20.04)不支持该字段,就得靠 ExecStartPre + aa-exec,但要注意:它只影响 ExecStart 启动的主进程,子进程默认继承——如果子进程 exec 了其他程序(比如调 sh -c "curl ..."),就得在 profile 里显式允许 /bin/sh/usr/bin/curl,否则会被拦。

  • 确认 systemd 版本:systemd --version;低于 245 就别设 AppArmorProfile
  • aa-exec -p /etc/apparmor.d/usr.bin.mydaemon -- /usr/bin/mydaemon 测试能否启动
  • profile 中必须声明 capability sys_admin, 才能操作 cgroup,否则 systemd 服务可能卡在 activating

复杂服务往往有多个二进制、临时目录、socket 路径,profile 很容易漏。建议先用 complain 模式跑满一个业务周期,再根据日志补全,别指望一次写对。

text=ZqhQzanResources