不要一上来就关闭 SELinux,五分钟带你搞懂 SELinux 是什么鬼?

今天分享一下SELinux。

在一些教程中,往往会让你一开始就将SELinux关闭,但生产环境中有些是不允许关闭的,是有必要深入学习一下SELinux。篇幅有点长,希望耐心看完。

在使用 Linux 的过程中,你可能遇到过下面这些场景:

权限全给了,服务还是无法访问文件;日志里一堆 “permission denied”,可你偏偏就是 root;改了配置,重启没报错,就是跑不起来……

如果你遇到这些灵异事件,那大概率是——SELinux 在背后搞鬼!

一、 什么是 SELinux?

SELinux(Security-Enhanced Linux) 是由美国国家安全局(NSA)最初开发的一套 安全访问控制机制,它为 Linux 系统提供了比传统用户权限(如 chmod、chown)更强、更细粒度的安全控制。

即使是 root 用户,也必须遵守它的规则!

二、 为什么要有 SELinux?

传统的 Linux 安全机制靠文件权限控制,但它有一个致命缺陷:

root 可以为所欲为。

一旦某个服务被攻击拿到 root 权限,攻击者就能横着走。而 SELinux 通过强制访问控制(MAC),哪怕你是 root,只要没被允许,也寸步难行。

三、SELinux是怎么工作的

1.  标签系统:给对象贴标签

在 SELinux 眼里,每个文件、目录、进程、端口都有一个“安全上下文”,本质就是一个标签。例如:

复制
ls -Z /var/www/html/index.html1.

上图 httpd_sys_content_t 就是该文件的 SELinux 类型标签。

2. 策略规则

系统有一套策略规则(Policy),明确规定:

哪种类型的进程,能访问哪种类型的对象,以什么方式访问(读、写、执行等)。

比如:

类型为 httpd_t 的进程(例如 nginx、httpd)可以读取类型为 httpd_sys_content_t 的文件不可以写这些文件,除非文件被标记为 httpd_sys_rw_content_t

只要行为不符合规则,哪怕权限没问题,访问照样被拒绝!

通过下面命令可以查看所有规则类型:

复制
semanage fcontext -l1.
3. 整体的工作过程:
复制
1. 进程发起访问请求(如httpd访问`/var/www/html/index.html`2. 内核SELinux模块拦截该请求 3. 获取进程和目标对象的安全上下文 - 进程类型:`httpd_t` - 文件类型:`httpd_sys_content_t` 4.AVC(访问向量缓存)中查找权限 - 有记录:允许或拒绝 - 无记录:查询SELinux策略决策模块 5. 策略模块判断是否允许访问 - 比如是否允许 `httpd_t` 类型访问 `httpd_sys_content_t` 文件进行`read`操作 6. 结果反馈内核:允许 or 拒绝 7. 内核执行或拒绝该访问操作 8. 如果被拒绝,则在日志中记录AVC拒绝信息(/var/log/audit/audit.log)1.2.3.4.5.6.7.8.9.10.11.12.13.

四、SELinux 的三种工作模式

使用 getenforce 命令可以查看当前模式:

复制
getenforce1.

三种模式如下:

模式

描述

Enforcing

强制执行 SELinux 策略,违规操作将被阻止

Permissive

只记录违规操作,不阻止(适合排查问题)

Disabled

完全关闭 SELinux

临时切换模式(重启后失效):

复制
setenforce 0 # 切换到 Permissive setenforce 1 # 切换回 Enforcing1.2.

永久修改需编辑配置文件 /etc/selinux/config:重启才生效

复制
SELINUX=enforcing # 可选值:enforcing、permissive、disabled # 也可以直接一条命令修改 sed -i "s#=enforcing#=disabled#g" /etc/selinux/config1.2.3.4.5.

五、经典场景

1. nginx 无法读取自定义目录

你把网站内容放到 /data/www,nginx 报 403:

复制
ls -Z /data/www1.

发现目录类型是 default_t,而不是 nginx 允许的类型。

临时解决方法:
复制
chcon -R -t httpd_sys_content_t /data/www1.
永久更改(推荐):
复制
# 会保存在SELinux策略数据库 semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?" restorecon -Rv /data/www1.2.3.
2. 服务监听端口被阻止

比如某服务想监听 8080 端口,结果启动失败。

查看当前允许的端口:
复制
# 如果没有8080端口就会被拦截 semanage port -l | grep http_port_t1.2.
添加允许的端口:
复制
semanage port -a -t http_port_t -p tcp 80801.
3. Docker 容器莫名权限问题

Docker 默认使用 container_t 类型运行容器,如果你挂载了宿主机目录,但标签不对,也会被 SELinux 拒绝。

解决方案之一:

复制
-v /data:/data:Z # 自动设置 SELinux 标签1.

六、SELinux相关常用命令

命令

用途

getenforce

查看当前 SELinux 模式

setenforce

临时切换模式

ls -Z

查看文件或目录的标签

ps -eZ

查看进程的标签

chcon

临时修改标签(重启失效)

restorecon

恢复默认标签(结合 semanage 使用)

semanage

配置永久标签、端口、布尔值等

七、到底要不要开启 SELinux?

下面是一些建议:

场景

建议

生产环境

强烈建议开启 Enforcing

测试环境

建议用 Permissive 模式排查问题

学习/开发环境

可关闭,但最好学会调试 SELinux

关闭 SELinux 虽然简单粗暴,但也等于把“系统最后一道防线”拆了,得不偿失。

SELinux 并不复杂,它只是更严谨。

当别人还在为“权限没问题却访问不了”头秃时,你已经能轻松用 semanage 和 restorecon 一键修复。

阅读剩余
THE END