AppArmor(Application Armor)是Linux内核的一个安全模块,通过每个程序的配置文件限制程序的功能,从而增强系统的安全性。它允许系统管理员为每个程序创建安全配置文件,以限制程序的功能和资源访问
AppArmor有两种工作模式:
- 强制执行模式(enforcement mode):配置文件中定义的策略将会被执行,并且会向系统日志报告违规尝试
- 抱怨模式(complainmode):配置文件中的策略不会被执行,但会记录违反策略的尝试
AppArmor的主要特点包括:
- 强制访问控制(MAC):补充传统的Unix自主访问控制(DAC)模型
- 基于路径的访问控制:与SELinux不同,AppArmor使用文件路径来确认文件
- 易于配置和管理:相比SELinux,AppArmor更简单易用
官网手册:https://gitlab.com/apparmor/apparmor/-/wikis/QuickProfileLanguage
快速使用
安装工具组件
apt install apparmor-utils apparmor-profiles apparmor-profiles-extra -y
初始化配置文件
aa-autodep 程序名
设置complain模式
aa-complain 程序名
运行程序,然后使用以下命令,命令将会对日志进行扫描,用户可以进行交互式放权
aa-logprof
测试一段时间后权限更改的差不多的了,就开启enforce权限
aa-enforce 程序名
基础配置文件
下面是根据上面的aa-logprof命令生成的配置文件,文件路径在/etc/apparmor.d/,文件名一般是路径,如/root/test则是root.test
# Last Modified: Tue Sep 10 15:11:57 2024
#记录配置文件的最后修改时间
abi <abi/3.0>,
#指定 AppArmor 的 ABI 版本
include <tunables/global>
#包含全局变量和设置
/root/test flags=(complain) {
#指定配置文件应用于 /root/test 脚本
#设置为 complain 模式,表示记录违规行为但不阻止
include <abstractions/base>
include <abstractions/bash>
include <abstractions/consoles>
#包含某些相关程序的权限设置
capability dac_read_search,
#允许脚本执行目录读取和搜索操作
#更多参数使用man capabilities查询
audit deny /var/log/nginx/error.log r,
#拒绝读取/var/log/nginx/error.log文件,并且audit表示将其行为记录到审计日志
/var/log/syslog r,
#允许读取 /var/log/syslog 文件。
owner /root/test r,
#如果文件属主是当前用户,则允许读取
}
加载配置
apparmor_parser -r -W /etc/apparmor.d/root.test
- -r:表示重新加载指定的配置文件,如果配置文件已经存在,它将被重新解析和加载。
- -W:表示在解析配置文件时显示警告信息。
移除配置
apparmor_parser -R /etc/apparmor.d/root.test
父子配置结构
/parent/profile {
/path/to/child1 cx -> child1,
/path/to/child2 cx,
/path/to/* cx,
/another/path/to/* cx -> child1,
profile child1 {
}
profile /path/to/child2 {
}
profile /path/to/child3 {
}
profile /path/to/child* {
}
}
- /path/to/child1 cx -> child1:
- 这表示当执行 /path/to/child1 时,将切换到 child1 配置文件
- /path/to/child2 cx:
- 这表示当执行 /path/to/child2 时,将切换到 /path/to/child2 配置文件
- /path/to/* cx:
- 这表示当执行 /path/to/ 目录下的任何文件时,将切换到相应的子配置文件
- 例如,执行 /path/to/child3 时,将切换到 /path/to/child3 配置文件
- 如果没有匹配的子配置文件,例如 /path/to/child4,将切换到 /path/to/child* 配置文件
- /another/path/to/* cx -> child1:
- 这表示当执行 /another/path/to/ 目录下的任何文件时,将切换到 child1 配置文件
- profile child1 {}:
- 这是 child1 配置文件的定义
- profile /path/to/child2 {}:
- 这是 /path/to/child2 配置文件的定义
- profile /path/to/child3 {}:
- 这是 /path/to/child3 配置文件的定义
- profile /path/to/child* {}:
- 这是 /path/to/child* 配置文件的定义,用作通配符匹配的回退配置文件
变量
# 定义变量
@{HOME}=/home
@{PROC}=/proc
# 使用变量
profile example_profile {
# 限制访问用户主目录
@{HOME}/** rw,
# 限制访问/proc目录
@{PROC}/** r,
}
通配符
*
:匹配零个或多个字符。例如,/home/*匹配/home/目录下的所有文件和子目录?
:匹配一个字符。例如,/home/user?匹配/home/user1、/home/user2等[ ]
:匹配括号内的任意一个字符。例如,/home/user[12] 匹配 /home/user1和/home/user2{ }
:匹配括号内的任意一个模式。例如,/home/{user1,user2}匹配 /home/user1和/home/user2**
:匹配任意数量的目录层级。例如,/home/**匹配/home/ 目录下的所有文件和子目录,包括子目录中的文件- [^]:反向匹配,例如,/home/user/[^a-z]*匹配/home/user/目录下所有不以小写字母开头的文件
文件权限
- r:读
- w:写
- a:追加
- x:执行
- m:内存映射可执行文件
- k:锁定文件,防止文件被删除或重命名(需要rw一起参与)
- l:链接到文件的权限
其他常用规则
网络规则
network
#允许所有网络操作。
network inet
#允许IPv4网络操作。
network inet6
#允许IPv6网络操作。
network raw
#允许原始套接字操作。
network packet
#允许数据包套接字操作。
network unix
#允许Unix域套接字操作。
network bluetooth
#允许蓝牙网络操作。
network bridge
#允许桥接网络操作。
network netlink
#允许Netlink套接字操作。
network packet
#允许数据包套接字操作。
network tcp
#允许TCP网络操作。
network udp
#允许UDP网络操作。
资源规则
profile example-profile {
rlimit as 1024;
#as表示地址空间限制
rlimit cpu 60;
#cpu表示 CPU 时间限制
}
常用参数值:
- core - 核心文件大小限制
- data - 数据段大小限制
- fsize - 文件大小限制
- locks - 文件锁定限制
- memlock - 内存锁定限制
- msgqueue - 消息队列大小限制
- nice - 优先级限制
- nofile - 打开文件描述符数量限制
- nproc - 进程数量限制
- rss - 常驻集大小限制
- sigpending - 挂起信号数量限制
- stack - 栈大小限制
信号规则
#include <tunables/global>
/usr/bin/example {
# 允许发送SIGKILL信号
signal send set=(kill) peer=/usr/bin/another_example,
# 允许接收SIGTERM信号
signal receive set=(term) peer=/usr/bin/another_example,
}