AppArmor是Ubuntu系统内置的强制访问控制(MAC)安全模块,它通过配置文件来限制每个进程能访问哪些文件、目录和网络资源。要定制细化进程访问权限,核心就是编辑/etc/apparmor.d/目录下对应程序的配置文件,用精确的路径规则和权限声明来收紧或放开特定进程的行为边界。这不是什么高深操作,但很多人要么不敢动,要么改错了导致程序崩溃,下面我把从原理到实操、从基础到进阶的完整流程一次性讲透。
AppArmor的工作原理很简单:每个受保护的程序都有一个"安全画像"(profile),这个画像就是一个文本配置文件,里面写满了这个程序被允许做什么、不允许做什么。当程序试图打开一个文件、执行一个操作时,内核会先查AppArmor的规则,匹配不上就直接拦截。Ubuntu默认已经给大量常用程序(比如Apache、MySQL、Firefox、Nginx)配好了画像,开箱即用。
你要做的"定制细化",本质上就是修改这些画像文件,让规则更精准。比如你的Web服务器只需要读/var/www/html/,那就把其他目录的读取权限全部砍掉;比如你的数据库进程不需要访问/home/,那就明确禁止。这样即使程序被攻击利用,攻击者能做的事情也被限制在极小范围内。
动手之前先摸清家底。打开终端,先看AppArmor是否在运行:
sudo aa-status
这条命令会列出所有已加载的profile以及它们当前是enforce(强制执行)还是complain(仅记录不拦截)模式。如果某个程序你想保护但还没配置,它不会出现在这里。
接着查看所有可用的配置文件:
ls /etc/apparmor.d/
你会看到一堆.d/后缀的文件,比如usr.sbin.mysqld、usr.bin.firefox。文件名中的斜杠被替换成了点号,这是AppArmor的命名规范。如果你要为一个新程序创建配置,也要遵循这个命名方式。
假设你有一个自定义程序/opt/myapp/bin/myapp需要保护,操作步骤如下:
第一步,用aa-genprof自动生成基础模板:
sudo aa-genprof /opt/myapp/bin/myapp
这个命令会让你运行一次程序,AppArmor会在后台监控它的所有文件访问行为,然后生成一个初始profile。但自动生成的规则通常比较宽泛,你需要手动精简。
第二步,编辑生成的配置文件:
sudo nano /etc/apparmor.d/opt.myapp.bin.myapp
文件内容大致长这样:
#include <tunables/global>
/opt/myapp/bin/myapp flags=(complain) {
#include <abstractions/base>
#include <abstractions/bash>
/opt/myapp/bin/myapp mr,
/opt/myapp/data/ rw,
/tmp/ rw,
/proc/* r,
/sys/* r,
}
注意flags=(complain),这表示当前是学习模式,只记录不拦截。确认规则没问题后,改成flags=(enforce)才会真正生效拦截。
AppArmor配置文件的语法并不复杂,但每个符号都有含义,搞错一个字符权限就完全不同。
路径规则:
/opt/myapp/data/ rw,
双星号表示递归匹配所有子目录和文件,rw表示读写权限。如果只写r就是只读,w就是只写,rx表示读和执行,x表示只执行。
精确匹配:
/opt/myapp/config.conf r,
没有通配符就是精确匹配这一个文件,比通配规则更安全。
拒绝规则(deny):
deny /home/ rw,
显式拒绝某个路径的访问。注意,AppArmor的规则是按顺序匹配的,先匹配到的规则生效。所以如果你前面写了一个宽泛的允许规则,后面的拒绝可能被覆盖。把拒绝规则放在允许规则前面,或者用更精确的路径来确保拒绝优先。
变量和抽象:
#include <abstractions/base>
这行是引入一个公共规则集,里面包含了基本的系统访问权限。如果你的程序不需要那么多基础权限,可以不引入,或者只引入你需要的部分。
五、实战案例:细化Nginx的访问权限以Ubuntu默认的Nginx为例,默认配置允许它访问很多路径。如果你只想让它服务/var/www/mysite/,可以这样改:
sudo cp /etc/apparmor.d/usr.sbin.nginx /etc/apparmor.d/usr.sbin.nginx.bak sudo nano /etc/apparmor.d/usr.sbin.nginx
修改关键部分:
# 只允许访问指定网站目录 /var/www/mysite/ rw, # 禁止访问其他网站目录 deny /var/www/ rw, # 只允许读取必要的配置 /etc/nginx/nginx.conf r, /etc/nginx/sites-enabled/mysite r, # 禁止修改配置文件 deny /etc/nginx/ w, # 日志只允许追加写入 /var/log/nginx/*.log w, deny /var/log/nginx/ rw,
改完后重载配置:
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx
然后用sudo aa-status确认Nginx的profile已经变成enforce模式。
AppArmor有一个很多人不知道的高级特性——change_profile和change_hat。如果你的程序有多个组件,比如一个主进程和一个处理上传的子进程,你可以让子进程切换到一个权限更低的子profile:
change_profile <lower_priv_profile>,
或者用hat机制(需要程序代码配合):
change_hat <upload_hat>,
这样即使主进程被攻破,攻击者在子进程里能做的事情也被进一步限制。这在处理不可信用户输入的场景下非常有用,比如Web应用的文件上传模块。
七、调试和排错——改崩了怎么办配置改错导致程序无法启动是常事。首先把模式改回complain:
flags=(complain)
然后查看系统日志找被拦截的操作:
sudo dmesg | grep apparmor sudo journalctl -xe | grep apparmor
日志会明确告诉你哪个进程试图访问哪个路径被拒绝了,根据这个信息补充允许规则即可。千万不要一上来就把所有规则都放开,那等于没配。
另外,Ubuntu的/etc/apparmor.d/local/目录是用来放本地自定义覆盖规则的。如果你不想直接改系统自带的profile,可以在local目录下创建同名文件,只写你要修改的部分,这样系统更新时不会覆盖你的改动。
第一,永远先用complain模式测试,确认无误再切换enforce。第二,遵循最小权限原则,只给程序运行必需的权限,多余的一律砍掉。第三,定期用aa-status和aa-logprof审查已有配置,发现异常访问及时收紧。第四,对关键服务做配置备份,改之前先cp一份。第五,如果你的程序是通过包管理器安装的,优先使用系统自带的profile,只在必要时才自定义。
AppArmor不是银弹,它不能替代防火墙、及时更新补丁等其他安全措施,但它是Ubuntu系统上最容易被忽视却最有效的纵深防御层之一。花半小时把关键服务的profile细化一遍,你的系统安全等级会实实在在提升一个档次。
