7.1 概述
7.1.1 概念
SELinux(Security-Enhanced Linux)是美国国家安全局联合开源社区开发的 强制访问控制(MAC)安全子系统,核心是约束服务进程仅能访问其必需的资源,避免越权操作。
通俗例子:下载的美图软件本应只处理图片,却偷偷监听浏览器密码------SELinux 会直接阻断这种"出格"行为。
7.1.2 核心作用
-
SELinux 域限制:约束服务程序的功能边界(比如 Nginx 不能做 SSH 的事);
-
SELinux 安全上下文:限制文件资源的访问范围(比如 Nginx 只能读自己的网页目录)。
7.1.3 SELinux 与传统权限的区别
| 对比维度 | 传统权限(DAC) | SELinux(MAC) |
|---|---|---|
| 控制逻辑 | 基于用户/用户组的自主访问 | 基于进程+文件的强制访问 |
| 核心对象 | 用户 | 进程(主体)+ 文件(目标) |
| root 权限 | 不受限制 | 同样受策略约束 |
实操感受:之前以为 root 能为所欲为,直到用 root 启动 Nginx 访问自定义目录被 SELinux 拦截,才明白 MAC 是"强制底线"。
7.1.4 进程访问文件的完整流程
-
进程发起访问请求;
-
SELinux 检查策略规则 + 主体与目标的安全上下文是否匹配(MAC 层面);
-
系统检查进程所属用户对文件的 rwx 权限(DAC 层面);
-
两步均通过才允许访问,任一失败则拒绝。
关键:SELINUX 是"第一道防线",即使文件权限设为 777,SELinux 不允许也无法访问。
7.2 SELinux 工作原理
7.2.1 核心名词解释
1. 主体(Subject)
-
想要访问资源的 进程(比如 nginx 进程、sshd 进程);
-
区别于 DAC 以"用户"为主体,MAC 直接约束"进程",更精准。
2. 目标(Object)
- 被访问的文件、目录或端口等资源(比如 /usr/share/nginx/html 目录)。
3. 策略(Policy)
-
预设的规则集合,避免管理员手动配置海量规则,默认两种核心策略:
-
targeted:默认策略,仅限制网络服务(Nginx、SSH、MySQL 等),对本地系统影响小; -
mls:多级安全策略,限制极严格,适合高安全场景(如军工、金融)。
-
4. 安全上下文(Security Context)
-
所有进程、文件都有唯一的"身份标识",格式:
身份:角色:类型:灵敏度(如system_u:object_r:httpd_sys_content_t:s0); -
进程能否访问文件,核心看 类型字段是否匹配(进程的"域" vs 文件的"类型")。
类比:主体是男生,目标是女生,安全上下文的"类型"就是两人的"择偶标准",策略是"匹配规则",匹配上才能"建立连接"。
7.2.2 文件安全上下文查看
1. 先启用 SELinux(基础前提)
# 安装必需组件
[root@server ~]# yum install selinux-policy selinux-policy-targeted -y
# 临时切换为宽容模式(避免直接启用强制模式导致服务崩溃)
[root@server ~]# vim /etc/selinux/config
SELINUX=permissive
# 重建文件安全上下文(必须操作,否则重启后不生效)
[root@server ~]# touch /.autorelabel
[root@server ~]# reboot
# 验证无误后,切换为强制模式(生产环境推荐)
[root@server ~]# vim /etc/selinux/config
SELINUX=enforcing
[root@server ~]# reboot
踩坑记:第一次没执行
touch /.autorelabel,重启后 SELinux 状态一直是 disabled,原来这个文件是触发上下文重建的关键。
2. 查看命令:ls -Z
# 查看单个文件
[root@server ~]# ls -Z anaconda-ks.cfg
system_u:object_r:admin_home_t:s0 anaconda-ks.cfg
# 查看目录(-d 只看目录本身)
[root@server ~]# ls -Zd /usr/share/nginx/html
system_u:object_r:httpd_sys_content_t:s0 /usr/share/nginx/html
3. 安全上下文字段解析(重点看第3个)
| 字段 | 含义 | 常见值 |
|---|---|---|
| 身份(Identify) | 所有者身份标识 | system_u(系统)、unconfined_u(普通用户) |
| 角色(Role) | 资源类型(进程/文件) | object_r(文件/目录)、system_r(进程) |
| 类型(Type) | 核心匹配字段 | httpd_sys_content_t(Nginx文件)、ssh_port_t(SSH端口) |
| 灵敏度(Sensitivity) | 安全级别 | s0(默认,数字越大越严格) |
小技巧:
seinfo -t可查看所有类型(需安装 setools-console),但不用记,用到时查就行。
7.3 SELinux 的启动、关闭与查看
7.3.1 三种运行模式
| 模式 | 作用 | 适用场景 |
|---|---|---|
| enforcing | 强制模式:拦截不合法请求并记录日志 | 生产环境(推荐) |
| permissive | 宽容模式:仅警告不拦截 | 测试/排障 |
| disabled | 关闭模式:SELINUX 不运行 | 仅本地测试(不推荐) |
7.3.2 模式管理命令(实操高频)
1. 查看当前模式
[root@server ~]# getenforce # 简单快速(推荐)
Enforcing
[root@server ~]# sestatus # 查看详细状态(含策略、配置文件模式)
2. 临时切换模式(重启失效)
[root@server ~]# setenforce 0 # 切换为宽容模式
[root@server ~]# setenforce 1 # 切换为强制模式
注意:
setenforce只能在 enforcing 和 permissive 之间切换,不能直接切到 disabled!
3. 永久切换模式(需重启)
[root@server ~]# vim /etc/selinux/config
SELINUX=enforcing # 改为 disabled 即永久关闭
SELINUXTYPE=targeted # 策略类型(默认 targeted 即可)
[root@server ~]# reboot
小提醒:/etc/sysconfig/selinux 与上述文件内容一致,改一个就行,避免重复修改。
7.3.3 关键配置文件说明
/etc/selinux/config # 核心配置文件
# 主要参数:
# SELINUX:指定运行模式(enforcing/permissive/disabled)
# SELINUXTYPE:指定策略类型(targeted/mls)
7.4 修改安全上下文(核心实操)
7.4.1 chcon 命令:临时修改(重启/restorecon 失效)
作用:手动调整文件/目录的安全上下文
常用格式
# 1. 直接指定类型(最常用)
chcon -R -t 目标类型 文件/目录
# -R:递归修改(目录及子文件)
# -t:指定类型字段(核心参数)
# 2. 参考范例文件(避免记类型,推荐)
chcon -R --reference=范例文件 目标文件/目录
实操示例
# 例1:将 /www/zy 目录改为 Nginx 可访问的类型
[root@server ~]# chcon -R -t httpd_sys_content_t /www/zy
# 例2:参考默认网页目录,批量修改
[root@server ~]# chcon -R --reference=/usr/share/nginx/html /www/zy
思考:
chcon是临时修改,适合测试场景;如果系统重启或执行restorecon,会恢复默认类型,长期用需用semanage。
7.4.2 restorecon 命令:恢复默认安全上下文
作用:将文件/目录的类型恢复为系统默认(抵消 chcon 的修改)
格式
restorecon -Rv 文件/目录
# -R:递归恢复
# -v:显示恢复过程
实操示例
# 恢复 /www/zy 目录的默认类型
[root@server ~]# restorecon -Rv /www/zy
小技巧:排障时如果怀疑上下文被改乱,先执行
restorecon试试,很多 403 问题能解决。
7.4.3 semanage 命令:永久修改(推荐)
作用:管理 SELinux 策略(永久修改上下文、端口规则等),需安装组件
# 安装依赖(必须步骤)
[root@server ~]# yum install policycoreutils-python-utils -y
常用场景
- 查询默认上下文
# 查看 /etc/passwd 的默认类型
[root@server ~]# semanage fcontext -l | grep /etc/passwd
- 永久添加端口规则(服务用非默认端口时必需)
# 格式:semanage port -a -t 端口类型 -p 协议 端口号
# 例:允许 Nginx 监听 7777 端口
[root@server ~]# semanage port -a -t http_port_t -p tcp 7777
- 布尔值管理(开关式控制权限)
# 查看所有布尔值
[root@server ~]# getsebool -a
# 开启布尔值(-P 永久生效,不加则临时)
[root@server ~]# setsebool -P httpd_can_network_connect 1
思考:布尔值就像"权限开关",比如
httpd_can_network_connect控制 Nginx 是否能访问外网,不用改复杂规则,开关就行。
7.5 核心实验(结合实操坑点)
实验1:Nginx 访问自定义目录(上下文配置)
场景:Nginx 配置 /www/zy 为网页目录,访问报 403
解决步骤
# 1. 确认 SELinux 是 enforcing 模式
[root@server ~]# getenforce
Enforcing
# 2. 查看目录上下文(默认是 default_t,Nginx 无权访问)
[root@server ~]# ls -Zd /www/zy
unconfined_u:object_r:default_t:s0 /www/zy
# 3. 永久修改上下文(推荐 semanage + restorecon)
[root@server ~]# semanage fcontext -a -t httpd_sys_content_t "/www/zy(/.*)?"
[root@server ~]# restorecon -Rv /www/zy
# 4. 重启 Nginx 测试
[root@server ~]# systemctl restart nginx
踩坑提醒:除了 SELinux,还要确保
/www/zy的文件权限是 755(Nginx 能读),否则还是 403!
实验2:Nginx 监听非默认端口 7777(端口规则配置)
场景:修改 Nginx 监听 7777 端口,重启服务失败
解决步骤
# 1. 查看 SELinux 允许的 HTTP 端口(默认没有 7777)
[root@server ~]# semanage port -l | grep http_port_t
# 2. 永久添加 7777 端口到 HTTP 端口列表
[root@server ~]# semanage port -a -t http_port_t -p tcp 7777
# 3. 重启 Nginx 测试
[root@server ~]# systemctl restart nginx
思考:SELinux 限制端口是为了防止服务滥用端口(比如 Nginx 偷偷监听 22 端口仿冒 SSH),生产环境要严格按需求添加端口。
实验3:SSH 监听非默认端口 2222(端口规则配置)
场景:修改 SSH 端口为 2222,重启 sshd 服务失败
解决步骤
# 1. 修改 SSH 配置文件
[root@server ~]# vim /etc/ssh/sshd_config
Port 2222
# 2. 添加 2222 端口到 SSH 端口规则
[root@server ~]# semanage port -a -t ssh_port_t -p tcp 2222
# 3. 重启 sshd 服务
[root@server ~]# systemctl restart sshd
小提醒:修改 SSH 端口后,记得在防火墙放通 2222 端口,否则连不上!
总结:SELinux 学习核心
-
核心逻辑:策略规则 + 安全上下文匹配,两步都过才能访问;
-
实操原则:生产环境用
enforcing模式,通过semanage永久配置,避免直接关闭; -
排障技巧:遇到 403/服务启动失败,先查 SELinux 日志(
grep "denied" /var/log/audit/audit.log),再用restorecon或semanage解决。
整体感受:SELINUX 看似复杂,但只要抓住"上下文匹配"和"端口/布尔值配置"两个核心,大部分问题都能解决,而且能极大提升系统安全性,值得花时间掌握!