Linux SELinux 安全加固与标签排错手册

传统文件权限只管「谁能碰这个文件」,管不了「谁在什么场景下能碰」。SELinux 补的就是这一层:它给每个进程、文件、目录、端口贴上标签,只按标签对标签的规则放行。这篇讲清 SELinux 的上下文结构、三种模式、模式切换的代价,以及标签被破坏后的几种修复手段,最后用一个真实故障收尾。文中命令名与选项均注明英文原意,完整清单见文末《附:命令英文全称速查表》。

本文概要:

项目 内容
文章主题 SELinux 的类型强制机制:上下文五字段 → 三种模式 → 模式切换 → 标签损坏修复 → 策略布尔值 → 故障实例
所属类别 Linux 系统管理 → 网络安全 → SELinux 强制访问控制
知识关键字 SELinux · context · type · targeted · enforcing · permissive · disabled · getenforce · setenforce · /etc/selinux/config · restorecon · semanage fcontext · /.autorelabel · getsebool · setsebool · boolean

概念图给出「进程标签 → 策略比对 → 资源标签」的主链路。概要表里的关键字分别落在:上下文与类型在第二章,模式与切换在第三章,标签修复手段在第四章,布尔值开关在第五章,故障实例在第六章。

一、SELinux 解决什么问题

1.1 文件权限管不到的地方

文件权限控制了哪些用户或用户组可以访问哪些文件,但没有限定访问文件的方式。

一个典型场景:结构化数据文件本该只允许特定程序写入,但只要有写权限,其他编辑器同样能打开并修改它,改坏了也没人拦。文件权限只管谁可以读、写、执行,管不了「怎么用」。

1.2 SELinux 的思路

Security Enhanced Linux(安全增强的 Linux)是一个额外的系统安全层。它的主要目标是防止已遭泄露的系统服务访问用户数据。

设想 Web 服务器进程被攻破,攻击者拿到进程权限,也就是 apache 用户与 apache 组的权限。此时它对文档根目录 /var/www/html 有读取权限,还能访问 /tmp、/var/tmp 以及其他任何全局可写的目录------这就是横向扩散的起点。

SELinux 的做法是强制执行一组访问规则,明确定义进程与资源之间允许的操作。每个进程、文件、目录和端口都带专门的安全标签,称为 SELinux 上下文(context) 。SELinux 策略用上下文来判断某个进程能否访问某个文件、目录或端口;除非有显式规则授予权限,默认情况下策略不允许任何交互。

这套机制叫类型强制(T ype E nforcement)。RHEL / CentOS 默认策略是 targeted,只对关键网络服务做强制,其余进程不受限。

二、SELinux 上下文

2.1 上下文的五个字段

上下文的完整写法是 用户:角色:类型:敏感度,用冒号分隔,跟在文件路径前面:

text 复制代码
unconfined_u : object_r : httpd_sys_content_t : s0   /var/www/html/file2
   用户          角色          类型                敏感度     文件
字段 含义 关注度
SELinux 用户 身份标识,与 Linux 用户不是一回事 低
角色(Role) 固定为 object_r 时对象是文件 低
类型(Type) targeted 策略真正用于判权的字段 高
敏感度(Level) 从 s0 起,只有多级安全(MLS)策略才细分 低

类型名通常以 _t 结尾,这是判断上下文是否「对」的关键。几个常见标签:

对象 上下文类型
Web 服务器守护进程 httpd_exec_t
Web 服务器网页文件 httpd_sys_content_t
Web 服务器监听端口 http_port_t
/tmp、/var/tmp tmp_t

2.2 默认策略下的放行与拒绝

  • SELinux 默认策略允许 apache 进程访问 /var/www/html 下的文件,以及其他带 httpd_sys_content_t 上下文的目录;
  • 策略禁止它访问标签不匹配的目录;
  • 在 SELinux 保护下,apache 进程不允许访问 /tmp 与 /var/tmp,因为这两处的标签是 tmp_t,与默认策略不匹配。

这就是上一节那个扩散场景被堵住的原理:即使进程权限足够,标签不匹配就过不去。

2.3 查看与设置上下文

许多处理文件的命令都带 -Z 选项,用于显示或设置 SELinux 上下文。

-Z 用法速查表
写法 作用 说明(英文原意)
ps -Z 查看进程的上下文 常配合 -C 进程名 精确筛选
ls -Z 查看文件或目录的上下文 ---
cp -Z 复制时把目标文件设为默认上下文 Z = SELinux context
mkdir -Z 新建目录时设为默认上下文 ---
id -Z 查看当前登录用户的上下文 ---
bash 复制代码
# 只看 sshd 进程的上下文,输出既有受限域也有不受限域
[root@zhb-m1 ~]# ps -C sshd -Z
LABEL                                            PID TTY     TIME CMD
system_u:system_r:sshd_t:s0-s0:c0.c1023          951 ?   00:00:00 sshd
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 1276 ? 00:00:00 sshd
system_u:system_r:sshd_t:s0-s0:c0.c1023         1261 ?   00:00:00 sshd

# 查看家目录的标签
[root@zhb-m1 ~]# ls -Z /home
unconfined_u:object_r:user_home_dir_t:s0 zhb

sshd_t 是受限域,unconfined_t 是不受限域------同一个进程名出现两种标签,说明 SELinux 是按「进程实例 + 策略」贴标签的,不是按程序名一刀切。

三、SELinux 的三种模式

模式 行为 用途
enforcing(强制) 强制执行访问控制规则,规则没明确允许就拒绝访问,并写入日志 默认模式,生产环境
permissive(宽容) 加载策略并处于活动状态,但不强制执行,只记录访问违规 测试与排错
disabled(禁用) 完全关闭 SELinux,不拒绝、不记录 排障临时手段

⚠️ 注意 :enforcing 与 permissive 之间可以随时在线互切,不需要重启 ;但只要跨到 disabled,或从 disabled 切回来,都必须重启系统。生产环境不要长期停在 permissive,它只记录不拦截,等于没有防护。

3.1 查看与临时切换

模式命令速查表
写法 作用 说明(英文原意)
getenforce 查看当前模式 get enforcement
sestatus 查看更详细的状态 含策略名、配置文件设定值、挂载点
setenforce 0 / setenforce Permissive 临时切到宽容模式 只改当前运行状态
setenforce 1 / setenforce Enforcing 临时切回强制模式 ---
bash 复制代码
[root@zhb-m1 ~]# getenforce
Enforcing

# 临时切到宽容模式
[root@zhb-m1 ~]# setenforce 0
# 等价写法
[root@zhb-m1 ~]# setenforce Permissive

# 切回强制模式
[root@zhb-m1 ~]# setenforce 1

3.2 永久修改默认模式

改配置文件 /etc/selinux/config:

bash 复制代码
[root@zhb-m1 ~]# vim /etc/selinux/config
SELINUX=enforcing
SELINUXTYPE=targeted
配置项 取值 含义
SELINUX enforcing / permissive / disabled 全局默认模式
SELINUXTYPE targeted / mls 加载哪种策略;targeted 只约束关键服务,mls 对所有进程细分域

3.3 用内核启动参数指定模式

在 GRUB 引导时向内核传参,可在系统启动阶段就定下模式:

参数 含义
enforcing=1 强制模式
enforcing=0 许可(宽容)模式
selinux=0 彻底禁用 SELinux
selinux=1 启用 SELinux;已写 enforcing= 时可省略

⚠️ 注意 :/etc/selinux/config 里写 SELINUX=disabled 的做法在新内核上已被标记为弃用 ------内核钩子仍会执行,只是不加载策略、不做拒绝,行为与真正关闭并不完全一致。要彻底关掉,应使用内核参数 selinux=0,它会覆盖配置文件里的设定。

四、标签损坏怎么修

SELinux 的绝大多数「怪问题」都源于标签不对。官方手册给出的判断信号是:日志里出现 file_t,通常意味着文件系统标签出了严重问题。

⚠️ 注意 :chcon 改的是文件当前的标签,重打标签(relabel)或 restorecon 后会被还原 。要长期生效,必须先用 semanage fcontext 把规则写进策略,再用 restorecon 应用。

标签修复用法速查表
写法 作用 说明(英文原意)
restorecon -Rv /var/www/ 按策略恢复默认标签 -R ecursive 递归,-verbose 显示改动
restorecon -nvr /home 只检查、不改动 -no-change 干跑模式
restorecon -F /path 强制重设完整上下文 Force,连用户、角色、范围一起改
semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?" 为目录树登记默认标签 add 新增记录
semanage fcontext -l 列出全部上下文规则 ---
semanage fcontext -m -t ... /path 修改已有记录 modify
semanage fcontext -d -t ... /path 删除记录 delete
chcon -t httpd_sys_content_t /var/www/html/a.html 临时改标签 ch ange context,relabel 后丢失
touch /.autorelabel 后重启 全盘重新打标签 开关文件,重启时生效

场景一:把自定义目录纳入 Web 目录的规则

bash 复制代码
# 先登记规则,再应用到现有文件
[root@zhb-m1 ~]# semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"
[root@zhb-m1 ~]# restorecon -Rv /web

场景二:只是想看看哪些文件的标签不对

bash 复制代码
[root@zhb-m1 ~]# restorecon -nvr /home

场景三:整机标签疑似错乱

创建开关文件后重启,SELinux 会在启动时自动重新标记整个文件系统:

bash 复制代码
[root@zhb-m1 ~]# touch /.autorelabel
[root@zhb-m1 ~]# reboot

⚠️ 注意:重新标记是一次全盘扫描,耗时长取决于文件数量与大小,重启后要留足时间让它跑完,中途断电中断会留下更乱的标签。

场景四:服务读不到自己的配置与数据文件

同一个坑换一种服务就会再踩一次:把文件挪个位置、或新建一个数据目录,文件权限(chmod / chown)看着都没问题,服务就是读不到。原因是每种服务在策略里都注册了自己的类型,路径一变,标签就不再匹配。

服务 它要读的东西 应有的类型
Web(Apache / Nginx) 站点目录与网页文件 httpd_sys_content_t
DNS(BIND / named) 区域文件 named_zone_t
数据库(MariaDB) 数据目录 mysqld_db_t

排查分两步走------先看当前标签,再看策略期望它是什么:

bash 复制代码
# 1. 看文件现在是什么标签
[root@zhb-m1 ~]# ls -Z /var/named/*.zone
unconfined_u:object_r:var_t:s0 /var/named/zhb.cloud.zone

# 2. 查策略里这个路径应该是什么标签
[root@zhb-m1 ~]# semanage fcontext -l | grep named_zone_t
/var/named(/.*)?   all files   system_u:object_r:named_zone_t:s0

两步一对比,var_t 与 named_zone_t 的差别就是服务读不到文件的原因。修法与场景一相同 :用 semanage fcontext 登记、再 restorecon 应用;服务自己的默认路径(如 /var/named)本来就登记好了,把文件放回原位往往比改标签更省事。

五、策略布尔值:不关 SELinux 也能放开单个功能

标签修对了、服务还是起不来,剩下的高频原因就是策略布尔值(boolean)没打开。布尔值是策略预留的开关,用来在不改标签、不关 SELinux 的前提下,放开某一类被策略写死的操作。比如允许 httpd 读取家目录、连数据库,或允许 ftp 写文件。

标签管的是「哪个进程能碰哪个资源」,布尔值管的是「这条已被允许/禁止的规则要不要打开」。两者互补:标签错就修标签,规则本就在策略里、只是默认关着,就改布尔值。

bash 复制代码
# 列出与 httpd 相关的全部布尔值及当前取值
[root@zhb-m1 ~]# getsebool -a | grep httpd
# 查询单个布尔值
[root@zhb-m1 ~]# getsebool httpd_enable_homedirs
# 临时打开,重启后失效
[root@zhb-m1 ~]# setsebool httpd_enable_homedirs on
# 永久打开
[root@zhb-m1 ~]# setsebool -P httpd_enable_homedirs on
布尔值用法速查表
写法 作用 说明(英文原意)
getsebool -a 列出全部布尔值及其取值 get s ELinux bool ean,常配合 grep 服务名 缩小范围
getsebool 名称 查询单个布尔值 只看 on / off
setsebool 名称 on 临时打开 只改内存里的当前值,重启回到策略默认
setsebool -P 名称 on 永久打开 -Persistent,写入策略,重启仍生效
semanage boolean -l 列出布尔值及用途说明 比 getsebool 多一列描述,用来判断该不该动这一项
semanage boolean -m --on 名称 修改布尔值 m odify,与 setsebool -P 等效

⚠️ 注意 :setsebool 不加 -P 只对当前运行状态生效,重启就还原------这是排错时最容易被忽略的一步:测试时用不带 -P 的写法确认有效,再补上 -P 固化。反过来,不确定某个开关的作用时,先用 semanage boolean -l 看描述,不要凭名字猜。

六、故障实例:破解 root 密码后登录失败

在 SELinux 为 enforcing 的环境里破解 root 密码,过程中会替换或修改 /etc/shadow。如果破解完成后没有执行 touch /.autorelabel,重启后用正确的密码登录会失败。

原因是被修改过的 /etc/shadow 文件标签已经不匹配策略,用户验证程序读不到它------密码(内容)明明是对的,文件(标签)却过不去。这就是「文件权限没问题、SELinux 拦住」的典型表现。

处理办法是在系统启动时给内核补参数:

text 复制代码
selinux=1 enforcing=0

先进宽容模式让系统起得来、能登录,再修标签:

bash 复制代码
# 恢复 /etc/shadow 的默认标签
[root@zhb-m1 ~]# restorecon -v /etc/shadow
# 或整机重新打标签后重启
[root@zhb-m1 ~]# touch /.autorelabel
[root@zhb-m1 ~]# reboot

处理完把模式改回 enforcing,并核对一遍结果:

bash 复制代码
[root@zhb-m1 ~]# getenforce
Enforcing
[root@zhb-m1 ~]# ls -Z /etc/shadow
system_u:object_r:shadow_t:s0 /etc/shadow

附:命令英文全称速查表

命令 / 缩写 英文全称 / 原意 作用
SELinux Security Enh anced Linux 内核级强制访问控制安全模块
getenforce get enforcement 查看当前模式
setenforce set enforcement 临时切换模式
sestatus S ELinux status 查看详细状态
restorecon restore context 按策略恢复文件默认标签
chcon ch ange context 临时修改文件标签
semanage s ELinux manage 管理策略元素(含上下文规则与布尔值)
fcontext f ile context 文件上下文规则
getsebool get s ELinux boolean 查询策略布尔值
setsebool set s ELinux boolean 修改策略布尔值(-P 永久)
boolean boolean 策略布尔值,策略里的开关
ps p rocess status 查看进程(-Z 看上下文)
context context 安全上下文,即安全标签
type type 类型,targeted 策略的判权字段
enforcing enforcing 强制模式,按策略拦截
permissive permissive 宽容模式,只记录不拦截
targeted targeted 默认策略,只约束关键网络服务
MLS M ulti-L evel Security 多级安全策略
relabel relabel 重新打标签

📚 参考资料(官方文档 · 中英双语)

英文原版(man7.org)

中文版

其余手册在服务器上直接查,不依赖网络、不占链接数:

bash 复制代码
man 8 selinux            # SELinux 总体说明与文件标签
man 8 getenforce         # 查看当前模式
man 8 setenforce         # 临时切换模式
man 8 restorecon         # 恢复默认上下文
man 8 semanage-fcontext  # 登记文件上下文规则
man 8 semanage-boolean   # 列出与修改策略布尔值
man 8 booleans           # 布尔值机制说明与 getsebool / setsebool

总结 :SELinux 的判权依据只有一条------进程的标签能不能碰目标的标签 ,文件权限在这一层之外。排错时先 getenforce 看模式、ls -Z / ps -Z 看标签:标签不对就用 restorecon 恢复、用 semanage fcontext 登记规则;标签没问题、规则却被默认关着,就去查布尔值,用 setsebool -P 开门。别把关掉 SELinux 当长期方案。觉得有用可以收藏,遇到过 SELinux 拦服务的情况欢迎在评论区聊聊排查过程。

相关推荐
其实防守也摸鱼2 小时前
SQL注入实验笔记
android·运维·数据库·安全·oracle·自动化
江屿风2 小时前
【Linux系统】【从【收尾】缓冲区到【新开】磁盘块:一节课打通文件系统底层原理】流食般投喂
linux·运维·服务器·人工智能·笔记
Pointer Pursuit2 小时前
编辑器Vim
linux·编辑器·vim
_upupup2 小时前
Linux中的权限解析
linux·服务器
曹牧2 小时前
Spring MVC : Controller 层URL划分
java·运维·服务器·前端
路漫漫其修远兮sjw2 小时前
Linux 运维知识点笔记(中级)
linux·运维·笔记
石一峰6992 小时前
Linux INPUT 与 I2C 子系统关联
linux·运维·计算机外设
jimmyleeee2 小时前
大模型安全之三十五:间接Prompt 注入测试全景指南
安全·prompt
宵时待雨2 小时前
linux笔记归纳24:多路转接select
linux·服务器·笔记·高并发