SELinux与AppArmor入门:强制访问控制配置与排错
「服务改了配置就是起不来日志也没报错」「明明给了 777 权限还是拒绝访问」——很多人被这类诡异问题坑过最后发现是 SELinux 或 AppArmor 在「多管闲事」。它们是 Linux 的**强制访问控制MAC**机制比传统的文件权限更底层、更严格。这一篇讲清 SELinux 和 AppArmor 的原理、配置和排错方法让你不再把「关掉它」当成唯一解法。一、什么是强制访问控制传统的 Linux 权限rwx、owner/group/other叫DAC自主访问控制文件属主可以随意决定谁能访问。问题在于——如果某个进程以 root 运行它就能访问任何文件一旦被攻破危害巨大。MAC强制访问控制在 DAC 之上再加一层由系统策略统一决定进程能访问哪些资源连 root 也要遵守。它就是「纵深防御」里的第 4 层见第 79 篇。维度DAC传统权限MACSELinux/AppArmor决定者文件属主系统策略root 能否绕过能不能粒度用户/组/其他进程/路径/标签目的基本的访问控制限制进程能力防提权二、两大流派MAC 实现 ├─ SELinux红帽系RHEL/CentOS/Rocky/Fedora—— 基于「标签」 └─ AppArmorDebian 系Ubuntu/Debian/SUSE—— 基于「路径」维度SELinuxAppArmor发行版RHEL/CentOS/RockyUbuntu/Debian模型标签label/context路径path配置复杂策略语言简单可读文本学习曲线陡缓先确认你的系统用哪个# 看 SELinuxgetenforce# 看 AppArmoraa-status三、SELinux 基础三种模式getenforce模式行为Enforcing强制执行策略违规被拒绝Permissive只记录不阻止排错时用Disabled完全关闭临时切换sudosetenforce0# 改 Permissivesudosetenforce1# 改 Enforcing配置文件/etc/selinux/config永久需重启SELINUXenforcing SELINUXTYPEtargeted⚠️ 排错黄金流程服务报「Permission denied」时先别急着关 SELinux改用 Permissive 模式测试# 1. 切换 Permissivesudosetenforce0# 2. 重启服务如果好了 → 是 SELinux 问题sudosystemctl restart myservice# 3. 切回 Enforcing查看拒绝日志找真因sudosetenforce1sudoausearch-mavc-tsrecent记住Permissive 是「排错工具」不是「解决方案」。找到真因后要么调上下文、要么开布尔值、要么写策略而不是永久禁用。查看拒绝日志# 看 AVC 拒绝记录sudoausearch-mavc-tsrecentsudojournalctl-taudit|grepAVC# 用 sealert 得到人类可读的建议sudodnfinstallsetroubleshoot-server-ysudosealert-a/var/log/audit/audit.logAVC denied就是「SELinux 拒绝了某操作」日志里会写清楚「哪个进程、对哪个资源、做了什么操作」以及修复建议。四、SELinux 上下文与布尔值SELinux 的核心是标签context。每个进程和文件都带一个安全上下文格式user:role:type:level system_u:object_r:httpd_sys_content_t:s0排障最关注的是type字段第三个。查看上下文# 文件上下文ls-Z/var/www/html/index.html# system_u:object_r:httpd_sys_content_t:s0 ...# 进程上下文ps-eZ|grepnginx# system_u:system_r:httpd_t:s0 nginx规则进程的 type如httpd_t必须能访问文件的 type如httpd_sys_content_t否则被拒。修改文件上下文场景把网站文件放到/web/而不是默认的/var/www/html/nginx 访问被拒。# 查看应该用什么上下文semanage fcontext-l|grephttpd_sys_content# 把 /web 目录标记为 web 内容类型sudosemanage fcontext-a-thttpd_sys_content_t/web(/.*)?# 应用规则到实际文件sudorestorecon-Rv/web关键点semanage fcontext是持久规则restorecon把规则应用到现有文件。只做前者不生效只做后者重启可能丢两者都要。布尔值boolean开关式策略SELinux 有一些「即开即用」的开关对应常见需求# 列出所有布尔值getsebool-a# 查看 web 相关getsebool-a|grephttpd# 开启「允许 httpd 连接网络」sudosetsebool-Phttpd_can_network_connect on-P表示持久化重启后仍生效。典型场景需求布尔值web 服务连数据库httpd_can_network_connect_db onweb 服务访问外网httpd_can_network_connect onftp 读写家目录ftp_home_dir on允许 http 写目录httpd_unified on先查布尔值再改上下文最后才考虑写策略——这是 SELinux 排错的优先级。五、SELinux 常见排错1. 服务起不来端口问题场景给 nginx 配了 8080 端口起不来。nginx: [emerg] bind() to 0.0.0.0:8080 failed (13: Permission denied)原因SELinux 只允许 httpd 绑定特定端口。# 查看 httpd 允许的端口semanage port-l|grephttp_port_t# 把 8080 加入 httpd 允许端口sudosemanage port-a-thttp_port_t-ptcp80802. 文件访问被拒场景网站文件放自定义目录403。# 查看 AVC 日志确认sudoausearch-mavc-tsrecent|grepnginx# 修正上下文见上文sudosemanage fcontext-a-thttpd_sys_content_t/web(/.*)?sudorestorecon-Rv/web3. 服务重启后上下文丢失cp/mv/tar有时不带上下文或文件系统不保留。用restorecon重建sudorestorecon-Rv/path4. 实在要用「文档化」的关闭如果确认某策略不适用于业务且不想关全局可以# 只对特定服务设白名单推荐semanage permissive-ahttpd_t# 完全禁用不推荐仅测试setenforce0permissive只让httpd_t域宽容其他仍受保护比全局关闭安全得多。六、AppArmor 基础Ubuntu/Debian 默认用 AppArmor它基于路径而不是标签profile 是纯文本易懂。查看状态sudoaa-statusapparmor module is loaded. 42 profiles are loaded. 38 profiles are in enforce mode. /usr/sbin/nginx /usr/bin/man ... 4 profiles are in complain mode.两种模式模式行为enforce强制执行违规拒绝complain只记录不阻止排错用切换模式# 改某 profile 为 complain排错sudoaa-complain /usr/sbin/nginx# 改回 enforcesudoaa-enforce /usr/sbin/nginx# 禁用某 profilesudoln-s/etc/apparmor.d/usr.sbin.nginx /etc/apparmor.d/disable/sudoapparmor_parser-R/etc/apparmor.d/usr.sbin.nginx排错# 查看拒绝日志sudodmesg|grep-iapparmorsudojournalctl|grepapparmorsudodmesg|grepapparmor\DENIED\生成/调整 profile# 让 AppArmor 学习一个程序的行为sudoaa-genprof /usr/bin/myapp# 从日志自动生成 profilesudoaa-logprof七、MAC 加固的正确心态做法评价出问题就Disabled/disable❌ 等于拆掉一层防线保持 Enforcing用 Permissive 定位✅ 正确姿势先调上下文/布尔值✅ 优先方案为特定服务设 permissive✅ 折中写自定义策略✅ 终极方案复杂SELinux/AppArmor 的初衷是「即使服务被攻破也限制它能造成的破坏」。关掉它等于放弃了这层保护。正确的做法是理解它为什么拒绝然后精准地放行必要操作。八、⚠️ 常见错误遇到问题直接setenforce 0。这是把安全防线拆了应该先定位再精准放行。改了semanage fcontext忘了restorecon。规则是规则还得应用到实际文件。getenforce显示 Enforcing 就慌。Enforcing 是正常状态说明策略在保护你。复制文件后上下文丢失。cp/mv可能不保留上下文用restorecon修复。chmod 777也解决不了。因为瓶颈在 MAC 而非 DAC权限再宽也没用。不知道系统用哪个 MAC。先getenforce/aa-status确认别对着 AppArmor 找 SELinux 的错。重装系统后策略没迁移。自定义的 SELinux 上下文、AppArmor profile 需要备份和迁移。在生产上直接改配置验证。应在测试环境验证策略改动避免影响生产。九、原理探究安全上下文与策略匹配SELinux 的标签模型SELinux 给每个主体进程和每个客体文件、端口、socket都打一个安全上下文。访问时内核做一件事主体进程上下文的操作 → 查策略 → 客体文件/端口上下文决策不看你「是谁root 还是普通用户」而看「进程带什么标签、文件带什么标签、策略允不允许这对标签交互」。举例nginx 进程 上下文system_u:system_r:httpd_t 网站文件 上下文system_u:object_r:httpd_sys_content_t 策略允许 httpd_t 读 httpd_sys_content_t → 通过 ✓ /etc/shadow 上下文system_u:object_r:shadow_t 策略不允许 httpd_t 读 shadow_t → 拒绝 ✗这就是为什么 nginx哪怕以 root 运行也读不了/etc/shadow——不是权限问题是 SELinux 策略层面根本不允许。这就是「强制访问控制」的威力连 root 都要服从策略。为什么按「端口」也要管不光是文件端口也有标签。http_port_t是允许 httpd 绑定的端口集合。这样即使攻击者让 nginx 绑定到别的端口也绑不上——限制的不是「谁能绑」而是「这个进程能绑哪些」。AppArmor 的路径模型AppArmor 更直观profile 里直接写路径规则/usr/sbin/nginx { /etc/nginx/** r, /var/www/** r, /var/log/nginx/** w, network tcp, }意思是「nginx 只能读/etc/nginx、/var/www写/var/log/nginx允许 TCP」。基于路径的好处是可读性好缺点是路径变动如软链接、mount容易绕过。两者对比的本质SELinux 基于标签资源带标签进程带标签策略管「标签对标签」。强势但复杂。AppArmor 基于路径策略管「进程对路径」。简单但不够细。无论哪种核心思想都是一样的给进程划定一个「只能碰这些」的笼子即使它被攻破也翻不出这个笼子。这就是「沙箱sandbox」和「最小权限」在网络访问控制层的落地。和容器安全的关系Docker/Kubernetes 的容器隔离也会用到 SELinux/AppArmor# docker 指定 SELinux 标签dockerrun --security-optlabeltype:container_t...# docker 指定 AppArmor profiledockerrun --security-optapparmordocker-default...K8s 的 Pod Security Context 也能指定seLinuxOptions。理解 MAC也是理解容器安全的基础。十、SELinux/AppArmor 速查表# SELinux getenforce# 看模式setenforce0/1# 临时切 Permissive/Enforcingls-Zfile# 看文件上下文ps-eZ|grepproc# 看进程上下文ausearch-mavc-tsrecent# 看拒绝日志semanage fcontext-a-tTYPE路径# 加上下文规则restorecon-Rv/path# 应用上下文semanage port-a-thttp_port_t-ptcp8080# 放开端口getsebool-a|grepxxx# 看布尔值setsebool-Pxxx on# 开布尔值semanage permissive-adomain_t# 单域宽容# AppArmor aa-status# 看状态aa-complain /path# 切 complainaa-enforce /path# 切 enforcedmesg|grep-iapparmor# 看日志aa-genprof /usr/bin/app# 生成 profile一句话收尾SELinux 用「标签」、AppArmor 用「路径」都是给进程划定活动范围连 root 也管。遇到「权限给了还被拒」先想它俩排错用 Permissive/complain 定位再用semanage/布尔值精准放行——别把关闭当解法那等于自断一层防线。至此第八篇「网络配置、远程与安全篇」10 篇全部完成。下一篇进入第九篇「存储、磁盘、备份与恢复篇」从磁盘分区开始把存储这块硬骨头啃下来。