跳到主要内容 深入理解 SELinux:Linux 系统安全的核心门禁机制 | 极客日志
Shell / Bash
深入理解 SELinux:Linux 系统安全的核心门禁机制 SELinux 是 Linux 的强制访问控制子系统,通过安全上下文和策略管理进程对资源的访问权限。文章介绍了其核心概念(主体、客体、策略)、三种工作模式(Enforcing、Permissive、Disabled)、安全上下文的查看与修改(chcon、semanage、restorecon)、布尔值管理以及故障排查方法(audit.log、sealert)。通过案例演示了如何配置 Apache 服务以符合 SELinux 策略,确保系统安全的同时满足业务需求。
DockerOne 发布于 2026/3/24 更新于 2026/4/18 5 浏览SELinux (Security-Enhanced Linux) 是一个由美国国家安全局 (NSA) 主导开发的强制访问控制 (MAC) 安全子系统。它不再仅仅依赖'钥匙',而是像一个一丝不苟的智能门禁系统。在这个系统里,每个人 (进程) 和每个房间 (文件、端口) 都被贴上了独一无二的电子标签 (安全上下文)。门禁系统手握一本厚厚的**'通行规则手册' (安全策略)**,严格规定了'谁'在什么时间可以进入'哪个房间'做什么事。
一、SELinux 的核心概念与工作流程 想象一下日常家宴,SELinux 就像家里的管家,确保一切井然有序。
核心概念 通俗比喻 描述 示例 主体 家庭成员/客人 发起动作的实体,通常是进程。 httpd 进程 (想端菜的厨师)客体 月饼/菜肴/房间 被操作的实体,可以是文件、目录、端口等。 /var/www/html/index.html (一盘月饼)策略 家规 一套规则的集合。定义了谁能对什么做什么事。 '只有厨师 (httpd_t) 才能碰厨房里的月饼 (httpd_sys_content_t)。' 安全上下文 身份胸牌/物品标签 最重要的概念。是附加到每个人/物上的安全标签。 system_u:object_r:httpd_sys_content_t:s0
安全上下文的结构:user:role:type:level
user (用户) : SELinux 用户,与 Linux 系统用户不同。
role (角色) : 用于角色基于访问控制 (RBAC)。
type (类型) : 最核心的部分 。策略主要是基于主体和客体的类型来制定规则的。type也常被称为域 (Domain) (当用于主体时) 和 类型 (Type) (当用于客体时)。
level (级别) : 用于多级别安全 (MLS),通常保持为 s0。
SELinux 的工作流程
当一个主体 (如 httpd 进程) 尝试访问一个客体 (如 /var/www/html/index.html 文件) 时,内核中的 SELinux 安全模块会拦截这个操作,并执行以下检查流程:
二、SELinux 的三种工作模式 SELinux 可以工作在三种不同的模式下。你可以临时切换模式,也可以永久修改配置文件。
模式 SELINUX 配置值描述 强制模式 enforcing默认且最安全 的模式。严格执行安全策略,任何违反策略的访问都会被阻止,并记录到审计日志 (/var/log/audit/audit.log)。宽容模式 permissive不阻止任何违反策略的访问,但会将其记录到审计日志中。此模式主要用于调试和排错 ,可以发现哪些操作会被阻止而不影响服务正常运行。 禁用模式 disabled完全关闭 SELinux。不推荐 在生产环境中使用。注意:从 disabled 切换到 enforcing 或 permissive需要重启系统。
1. 常用管理命令 (临时切换与查看)
sestatus
getenforce
setenforce 0
setenforce 1
2. 通过配置文件修改 (永久生效) 要永久更改 SELinux 的工作模式,你需要编辑其主配置文件。
配置文件路径 :/etc/selinux/config
找到 SELINUX= 这一行。
将其值修改为你期望的模式:enforcing, permissive, 或 disabled。
SELINUX=enforcing
SELINUXTYPE=targeted
如果你将模式从 enforcing 或 permissive 修改为 disabled,或者反之,必须重启系统 才能使更改完全生效。
如果你只是在 enforcing 和 permissive 之间切换,修改配置文件后,新模式会在下次系统启动时自动应用,无需立即重启。但如果你想立即生效,仍需配合 setenforce 命令临时切换。
三、SELinux 安全上下文 管理文件和目录的安全上下文是日常 SELinux 运维中最常见的操作。
安全上下文的结构:user:role:type:level
user (用户) :SELinux 用户,与 Linux 系统用户不同。
system_u—— 系统进程或内核使用的用户。
user_u—— 普通登录用户对应的 SELinux 用户。
unconfined_u—— 不受 SELinux 限制的自由用户(常见于桌面环境)。
role (角色) :用于角色基于访问控制 (RBAC)。
常见示例:
object_r—— 文件、目录等客体角色。
system_r—— 系统进程角色。
user_r—— 普通用户角色。
type (类型) :最核心的部分 。策略主要是基于主体和客体的类型来制定规则的。
常见示例:
httpd_t—— Apache Web 服务进程类型。
httpd_sys_content_t—— Web 内容文件类型。
sshd_t—— SSH 服务进程类型。
var_log_t—— 系统日志文件类型。
level (级别) :用于多级别安全 (MLS),通常保持为 s0。
system_u:object_r:httpd_sys_content_t:s0—— Web 目录下文件的常见安全上下文。
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023—— 不受限用户的完整上下文标签。
1. 查看安全上下文 (ls -Z, ps -Z)
ls -Z /etc/passwd
ls -ldZ /var/www/html
ps -aux |grep httpd
2. 临时修改安全上下文 (chcon) chcon 用于临时修改文件或目录的安全上下文,适合快速测试,但重启或 restorecon 后会失效。
语法: chcon -t <type> <file_path>
mkdir -p /tmp/demo_web
echo "Hello from SELinux test" |tee /tmp/demo_web/index.html
sed -i 's#DocumentRoot "/var/www/html"#DocumentRoot "/tmp/demo_web"#' /etc/httpd/conf/httpd.conf
sed -i 's#<Directory "/var/www/html">#<Directory "/tmp/demo_web">#' /etc/httpd/conf/httpd.conf
systemctl restart httpd
curl http://localhost
ls -Z /tmp/demo_web
chcon -R -t httpd_sys_content_t /tmp/demo_web
systemctl restart httpd
curl http://localhost
restorecon -Rv /tmp/demo_web
curl http://localhost
3. 永久修改与恢复安全上下文 (semanage fcontext, restorecon) 使用 semanage fcontext定义永久规则,再用 restorecon应用生效,是生产环境的正确做法。
mkdir -p /srv/website
echo "Welcome to my site" |sudotee /srv/website/index.html
sed -i 's#DocumentRoot "/var/www/html"#DocumentRoot "/srv/website"#' /etc/httpd/conf/httpd.conf
sed -i 's#<Directory "/var/www/html">#<Directory "/srv/website">#' /etc/httpd/conf/httpd.conf
systemctl restart httpd
curl http://localhost
ls -ldZ /srv/website
semanage fcontext -a -t httpd_sys_content_t "/srv/website(/.*)?"
restorecon -Rv /srv/website
ls -Z /srv/website
systemctl restart httpd
curl http://localhost
四、管理 SELinux 布尔值 SELinux 策略并非一成不变。布尔值 (Booleans) 是一种开关,允许管理员在不修改核心策略的情况下,动态调整某些策略规则的行为。
常用管理命令:
getsebool -a:列出所有的 SELinux 布尔值及其当前状态 (on/off)。
setsebool [-P] <boolean_name> <on|off|1|0>:设置一个布尔值的状态。
不带 -P 选项:临时修改,重启后失效。
带 -P 选项:永久修改 (Persist),会将设置写入策略文件。
getsebool -a |grep httpd
setsebool -P httpd_can_network_connect on
五、故障排查 当 SELinux 阻止了某个正常操作时,排查问题的关键在于分析日志。
审计日志 : /var/log/audit/audit.log记录了所有被 SELinux拒绝 (denied) 的操作。
setroubleshoot 服务 : 这个服务会监控 audit.log,并将复杂的拒绝信息翻译成人类可读的建议,通常记录在 /var/log/messages 中,并提供解决问题的具体命令。
sealert 工具 : (需要安装 setroubleshoot-server) sealert 是一个命令行工具,可以更直观地分析拒绝日志。
sealert -a /var/log/audit/audit.log
六、综合案例:保护我们的家庭相册网站 场景描述:
你想搭建一个简单的家庭相册网站,存放和分享家人团聚的照片。为了方便管理,你决定将所有照片存放在 /home/user/photo_gallery 目录下,并希望通过 Apache (httpd) 服务来展示这些照片。然而,SELinux 这位尽职的'管家',默认是不允许厨师 (httpd 进程) 随便进入家庭成员的私人房间 (/home/user/) 拿取物品 (照片) 的。
yum install -y httpd
mkdir -p /home/user/photo_gallery
echo "<h1>Happy Mid-Autumn Festival!</h1><img src='moon.jpg'>" > /home/user/photo_gallery/index.html
修改 Apache 配置文件:
编辑 /etc/httpd/conf/httpd.conf,将 DocumentRoot 和 <Directory> 指令的路径修改为你的照片目录。
DocumentRoot "/home/user/photo_gallery"
<Directory "/home/user/photo_gallery" >
Require all granted
</Directory>
systemctl restart httpd
curl http://localhost
查看审计日志 ,你会发现 SELinux 拒绝了 httpd 进程访问 /home/user/... 目录下的文件。
grep"avc: denied" /var/log/audit/audit.log |grep httpd
ls -ldZ /home/user/photo_gallery
你会发现它的类型很可能是 user_home_t,这是用户家目录的标准类型,默认不允许 httpd_t进程读取。
解决问题 - 使用 SELinux 布尔值 (更安全的方式)
直接修改 /home 目录下文件的上下文是一种可行但不推荐的做法,因为它破坏了家目录的默认安全策略。SELinux 提供了一个更优雅、更安全的开关——布尔值。
查找相关布尔值 :我们猜测应该有一个允许 httpd 读取用户家目录内容的开关。
getsebool -a |grep httpd |grep home
你很可能会找到一个名为 httpd_enable_homedirs 的布尔值,它默认是 off。
永久开启该布尔值 :
setsebool -P httpd_enable_homedirs on
现在,即使在强制模式下,你的相册网站也应该可以正常访问了!通过调整 SELinux 的'家规'(布尔值),我们在没有破坏整体安全结构的前提下,满足了我们的特殊需求。
练习题 题目一:查看状态
写出一条命令,查看当前 SELinux 的完整状态,包括模式、策略类型等。
题目二:切换模式
如何将 SELinux 临时切换到宽容模式?
题目三:查看文件上下文
如何查看 /home 目录自身的安全上下文?
题目四:查看进程上下文
如何查看当前 bash shell 进程的安全上下文?
题目五:临时修改上下文
在 /tmp 目录下创建一个空文件 test.log。写出一条命令,将其类型临时修改为 var_log_t。
题目六:永久修改上下文策略
你计划将 /data/mysql 目录用作 MySQL 数据库的存储路径。写出一条命令,添加一条策略,使得该目录及其下所有内容默认的安全上下文类型为 mysqld_db_t。
题目七:应用上下文策略
接上题,写出一条命令,立即应用你刚刚添加的策略到 /data/mysql 目录。
题目八:查看布尔值
如何查看所有与 FTP 服务 (ftpd) 相关的 SELinux 布尔值?
题目九:永久修改布尔值
写出一条命令,永久允许 Apache (httpd) 执行 CGI 脚本 (对应的布尔值通常是 httpd_enable_cgi)。
题目十:日志分析
当你的服务因 SELinux 而无法启动时,你首先应该检查哪个日志文件来寻找拒绝 (denied) 记录?
题目十一:chcon vs restorecon
简述 chcon 和 restorecon 命令在修改文件上下文时的主要区别。
题目十二:setenforce 的持久性
使用 setenforce 0 命令后,如果重启系统,SELinux 会处于什么模式?
题目十三:semanage 的作用
semanage fcontext 命令直接修改了文件系统上的安全上下文吗?如果不是,它修改了什么?
题目十四:排错流程
描述一个排查 SELinux 相关问题的基本流程 (至少三步)。
题目十五:综合应用
你需要让 vsftpd 服务能够读写 FTP 用户的家目录。这通常需要开启一个布尔值。请写出查找并永久开启这个布尔值的完整命令序列 (假设该布尔值中包含'ftp'和'home'关键词)。
答案与解析 touch /tmp/test.log
chcon -t var_log_t /tmp/test.log
semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?"
restorecon -Rv /data/mysql
setsebool -P httpd_enable_cgi on
答案十:
应首先检查 /var/log/audit/audit.log 文件。
答案十一:
chcon:直接、临时地修改文件在文件系统上的当前上下文。 restorecon:不直接修改,而是根据 semanage 定义的策略来恢复文件的正确上下文。
答案十二:
SELinux 会恢复到 /etc/selinux/config 文件中定义的永久模式 (通常是 enforcing)。
答案十三:
不是。它修改的是 SELinux 的策略数据库。
答案十四:
先用 getenforce/sestatus 确认 SELinux 状态 → 再用 audit2why 或检查 /var/log/audit/audit.log 找出被拒绝的操作原因 → 最后根据需要临时调整策略(setsebool/写 policy 模块)或修改文件上下文(restorecon/semanage fcontext)来解决。
getsebool -a |grepftp|grep home
setsebool -P ftpd_full_access on
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
JSON美化和格式化 将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online