物理主机 SELinux 拒绝排查:从 AVC 记录到标签修复

物理主机 SELinux 拒绝排查:从 AVC 记录到标签修复

网页文件从原目录移到 /srv 后,httpd 返回 403;文件可读,服务也在运行,此时不应直接扩大权限或关闭 SELinux。普通文件权限、服务授权配置和强制访问控制是三层不同的检查。本文以 AlmaLinux 9 上已有的 httpd 测试虚拟主机为例,把失败请求与 AVC 记录关联,再修复持久化标签,最后验收服务与访问边界。

一、固定测试范围与原始状态

CloudDDR 物理主机可选择 AlmaLinux 9。付款后在控制台查看凭据,通过 SSH 接入;多个地址时使用第一个地址。以下操作需要管理员权限,只在隔离测试环境执行,不覆盖现有业务目录,不修改监听地址或防火墙。

前提是 httpd 已安装,测试虚拟主机和访问入口已经配置。先保存该虚拟主机配置,并记录原来的 DocumentRoot。缺少排查工具时安装对应软件包,然后确认安全模式与审计服务:

sudo dnf install policycoreutils-python-utils
getenforce
sestatus
sudo systemctl status auditd --no-pager
sudo semanage fcontext -l -C
sudo semanage permissive -l

预期全局为 Enforcing,且 httpd 所处域没有被单独设为 permissive。若审计服务未正常运行,先恢复证据采集,不能用“日志没有拒绝记录”证明访问未受限制。保存本地标签映射列表,后续才能区分原有规则与本次新增规则。

setenforce 0 不是修复结果。关闭强制检查后请求成功,只能提供排查线索,不能证明恢复 enforcing 后仍可运行。

二、先排除普通权限与配置错误

创建专用测试目录,内容只放一行验收标记。目录允许遍历,文件允许读取;这些权限仅适用于公开测试内容,不用于密钥、备份或业务数据。

sudo install -d -m 0755 /srv/selinux-lab
printf 'selinux-lab-ok\n' | sudo tee /srv/selinux-lab/index.html
sudo chmod 0644 /srv/selinux-lab/index.html
namei -l /srv/selinux-lab/index.html
ls -ldZ /srv/selinux-lab
ls -lZ /srv/selinux-lab/index.html

在已有测试虚拟主机内,将文档根目录及对应目录授权改为:

DocumentRoot "/srv/selinux-lab"

<Directory "/srv/selinux-lab">
    AllowOverride None
    Options -Indexes
    Require all granted
</Directory>

修改前核对配置包含关系,避免另一个目录段覆盖授权。用 httpd -t 检查语法,用 httpd -S 核对请求命中的虚拟主机,成功后才 reload。

将 Shell 变量 CHECK_URL 设置为真实测试入口,路径指向 /index.html。入口必须匹配该虚拟主机;不要把凭据写进 URL。请求时检查响应正文,而不是只看连接成功:

sudo httpd -t
sudo httpd -S
sudo systemctl reload httpd
curl --fail --show-error "$CHECK_URL"

若失败,先阅读 httpd 错误日志。父目录缺少执行权限、虚拟主机命中错误、授权规则拒绝,都可能产生相似现象。此时递归执行宽权限修改既不能解决标签问题,也会扩大暴露范围。

三、用 AVC 找到主体、对象与动作

记录请求发生时间,并只重现一次失败操作,再查询同一时段的拒绝记录:

sudo ausearch -m AVC,USER_AVC -ts recent -i
ps -eZ | grep '[h]ttpd'
matchpathcon -V /srv/selinux-lab/index.html

AVC 中重点查看 scontext、tcontext、tclass 和被拒绝的权限。scontext 表示发起访问的进程域,tcontext 表示目标对象的安全上下文;文件读取与目录搜索是不同动作,不能只凭进程名判断。

应把记录中的路径、进程及时间与失败请求对应。目录搜索被拒绝时,还需检查路径上各级目录;只修复最终文件可能没有效果。若日志没有路径信息,可结合审计事件序号查看同一事件的其他记录。

没有 AVC 不等于确定无关。先核对时间范围、审计状态和服务实际进程域;仍无关联证据时,回到应用配置与普通权限排查,不盲目添加允许规则。也不要把历史拒绝记录全部送进策略生成工具,它们可能来自其他业务。

四、持久化修复网页内容标签

对于供 httpd 读取的普通静态内容,httpd_sys_content_t 是已有策略中的用途类型。只有证据表明测试路径标签不符合用途时,才添加精确映射:

sudo semanage fcontext -a -t httpd_sys_content_t \
    '/srv/selinux-lab(/.*)?'
sudo restorecon -Rv /srv/selinux-lab
matchpathcon -V /srv/selinux-lab/index.html
ls -lZ /srv/selinux-lab/index.html

若完全相同的表达式已经存在,应核对原规则,必要时用 -m 修改,而不是继续叠加。表达式只覆盖测试目录,不把整个 /srv 改成网页内容类型。semanage 保存路径与类型的映射,restorecon 才将预期上下文应用到现有文件。

chcon 直接改当前标签,却不建立持久映射,因此不能替代这一步。后续重标记可能撤销临时修改。

静态目录不需要服务写入。不要为了消除一次拒绝,把全部内容换成可写类型,也不要顺手打开无关布尔值。确实存在上传、缓存等写入需求时,应划出独立目录,按实际动作单独设计权限与标签。

五、验收恢复结果并保留回退路径

保持 enforcing,再访问同一入口,确认正文包含 selinux-lab-ok,同时检查是否出现与该请求关联的新 AVC。随后再次执行 restorecon 并重启测试服务,重复请求,验证修复不依赖临时标签或旧进程状态。

getenforce
sudo restorecon -Rv /srv/selinux-lab
sudo systemctl restart httpd
curl --fail --show-error "$CHECK_URL"
sudo ausearch -m AVC,USER_AVC -ts recent -i

验收还应包含反向检查:请求不存在的文件应失败;测试目录不应允许目录索引;服务没有新增非预期监听;本地标签变更仅覆盖约定路径。这些检查分别验证应用行为、配置和变更范围,不能互相替代。

结束实验时,先恢复原虚拟主机配置,通过语法检查并 reload,再清理测试目录。本次确实新增的映射可以删除;原有映射若被修改,应恢复记录下来的类型。清理后,对保留路径执行 restorecon。

最终记录保留失败请求、关联 AVC、修改前后标签、映射表达式和重启后的响应结果。一次请求成功只是功能恢复;安全模式未改变、映射可重建、访问范围未扩大,才构成完整的修复验收。

常见问题

网页返回 403 就能确定是 SELinux 吗?

不能。还需检查目录遍历权限、文件读取权限和 httpd 授权配置,并把失败请求与同一时段的 AVC 记录对应;没有关联证据时,不应按 SELinux 故障处理。

为什么不用 chcon 或直接生成允许策略?

chcon 的标签可能被 restorecon 重置。标准网页目录应使用 semanage fcontext 配合 restorecon 持久化标签;生成允许策略前,应先排除错误标签、路径配置和已有策略开关的问题。

AMD EPYC 7543P 独享物理主机,$447/月起。

物理主机配置,从内存档位开始

AMD EPYC 7543P,128GB 与 256GB DDR4-3200 ECC 两档。