当前位置: 首页 > news >正文

RHCSE--SELinux

1. SELinux 的定义与核心价值

  • 定义:SELinux(Security-Enhanced Linux,安全增强型 Linux)是集成到 Linux 内核中的强制访问控制(MAC)安全机制,通过预先定义的 “策略规则” 限制进程(主体)对文件、端口等资源(客体)的访问,即使进程拥有 root 权限,也只能执行被允许的操作。

  • 核心价值:

    • 解决 “传统权限(DAC)的缺陷”:传统 Linux 权限(读 / 写 / 执行、用户 / 组 / 其他)是 “自主访问控制”,root 用户拥有无限权限,一旦进程被劫持(如黑客入侵 Web 服务),攻击者可利用 root 权限肆意破坏;SELinux 是 “强制访问控制”,即使是 root 进程,超出规则的操作也会被禁止。

      1.进程提权 / 越权风险剧增

      • 场景:web 服务器(如 Nginx)被黑客入侵,恶意进程以 nginx 用户身份运行;

      • 无 SE Linux:若 nginx 用户因配置失误拿到过高权限(如能访问 /etc/passwd、/root 目录),恶意进程可直接读取密码文件、篡改系统配置,甚至提权为 root;

      • 有 SE Linux:即使 nginx 用户有一般权限,SE Linux 会限制 httpd_t 域只能访问预设资源(如 /var/www),无法触碰系统敏感文件。

      1. 难以追溯恶意行为

      • SE Linux 会记录详细的访问审计日志(/var/log/audit/audit.log),包括 “哪个进程、因什么策略被拒绝访问”;

      • 无 SE Linux:仅能通过一般权限日志(如 /var/log/secure)追踪用户操作,无法定位进程级的恶意访问(如某个后台进程偷偷读取敏感文件)。

      1. 依赖人工配置,容错率极低

      • 一般权限依赖管理员手动配置(如 chmod、chown),难免出现失误(如误设 777 权限);

      • 无 SE Linux:一次配置失误就可能导致敏感资源暴露,且难以发现;

      • 有 SE Linux:即使一般权限配置不当,强制访问策略仍能兜底,降低配置失误的影响。

    • 最小权限原则:为每个进程分配 “刚好够用” 的权限(如 httpd 进程只能访问 Web 目录和 80 端口,无法读写 /etc/passwd),限制攻击面。

    • 合规性要求:满足金融、医疗等行业的安全合规标准(如 PCI DSS),必须启用强制访问控制机制。

2. SELinux 与传统 Linux 权限(DAC)的区别(关键对比)

SELinux(安全增强型 Linux)与 Linux 一般权限(DAC,自主访问控制)是 “双重防护” 关系:一般权限管 “谁(用户 / 组)能对资源(文件 / 目录)做什么(读 / 写 / 执行)”,SELinux 管 “哪个进程能对哪个资源(按标签)做什么操作”,两者互补且 SELinux 优先级更高;没有 SELinux 会失去 “强制访问控制” 的最后一道防线,恶意进程、权限溢出等风险大幅升高。

特性一般权限(DAC,自主访问控制)SELinux 权限(MAC,强制访问控制)
控制主体以 “用户 / 组 / 其他(u/g/o)” 为核心,比如 root 用户、www 组。以 “进程(域)” 和 “资源(类型)” 为核心,基于标签(上下文)控制。
控制逻辑资源所有者自主决定权限(如 chmod 755 开放读执行),谁拿到权限就能操作。系统强制按预设策略执行,即使文件权限是 777,进程无 SE Linux 授权也无法访问。
权限标识r(读)、w(写)、x(执行),用 ls -l 查看。进程标签(domain,如 httpd_t)、资源标签(type,如 httpd_sys_content_t),用 ls -Z 查看。
优先级低:只要 SE Linux 禁止,即使一般权限允许也无法访问。高:覆盖一般权限,是最后一道防护。
防护目标防止 “用户误操作”(如普通用户删系统文件)、“合法用户越权”。防止 “恶意进程提权”(如黑客入侵 web 服务后访问 /etc/passwd)、“服务越权访问”。

2. 实际访问流程:先过一般权限,再过 SE Linux

当进程尝试访问资源(如 httpd 读 /var/www/html/index.html),系统会按以下顺序校验:

  1. 一般权限校验:httpd 运行的用户(如 apache)是否有文件的读权限(r),无则直接拒绝;

  2. SE Linux 校验:httpd 进程的域(httpd_t)是否被允许访问文件的类型(httpd_sys_content_t),无则拒绝。

举例:若 /var/www/html/index.html 权限是 777(一般权限允许所有人读),但 SE Linux 策略禁止 httpd_t 访问该文件类型,httpd 仍无法读取。

二、SELinux 核心原理:搞懂 “怎么工作”

这是 SELinux 的技术核心,需讲清 “访问控制的底层逻辑”,重点突破 “安全上下文” 和 “策略规则” 两个核心概念。

1. SELinux 的基本模型:主体、客体、策略、安全上下文

SELinux 的访问控制基于 “主体(Subject)→ 客体(Object)→ 策略规则(Policy)” 的三元模型,核心是通过 “安全上下文” 标识主体和客体的 “身份”,再通过策略规则判断是否允许访问。

  • 主体(Subject):指 “正在运行的进程”(如 httpd、sshd 进程),每个进程都有 SELinux 安全上下文。

  • 客体(Object):指 “被访问的资源”(如文件、目录、端口、设备等),每个客体也有 SELinux 安全上下文。

  • 策略(Policy):预定义的 “规则集合”,规定 “哪些主体(进程)可以访问哪些客体(资源)”,是 SELinux 的 “大脑”。

  • 安全上下文(Security Context):SELinux 给主体和客体打上的 “身份标签”,格式为 user:role:type:level(前三者是核心,level 用于 MLS 策略),访问控制的核心是 “比较主体和客体的安全上下文是否匹配策略规则”。

2. 安全上下文:SELinux 的 “身份标签”(核心中的核心)

安全上下文是 SELinux 最抽象也最关键的概念,需拆解结构并结合实例讲解:

(1)安全上下文的组成(以 unconfined_u:object_r:httpd_sys_content_t:s0 为例)

字段含义核心作用示例(httpd 相关)
user(用户)SELinux 用户(非 Linux 系统用户),标识 “访问者类型”区分不同类型的访问主体(如系统进程、用户进程)unconfined_u(不受限用户,如 root 进程)、system_u(系统进程)
role(角色)SELinux 角色,关联 “用户可执行的操作”限制用户 / 进程的 “职责范围”(如系统角色、用户角色)object_r(客体角色,用于文件 / 资源)、system_r(系统进程角色)
type(类型)最核心的字段,主体的 type 称为 “域(domain)”,客体的 type 称为 “类型”策略规则主要基于 type 定义(如 httpd_t 进程能否访问 httpd_sys_content_t 文件)主体 type:httpd_t(httpd 进程的域);客体 type:httpd_sys_content_t(Web 目录的类型)
level(级别)用于 MLS(多级安全)策略,标识资源的 “敏感程度”(如 s0s1:c0.c1023实现 “高敏感资源只能被高权限进程访问”仅在 MLS 策略中生效,默认 targeted 策略不常用

主体(进程)能否访问客体(文件 / 端口等资源),取决于 “主体的 type” 与 “客体的 type” 之间是否存在允许访问的规则(allow 规则)

  • httpd 进程的 SELinux 类型是 httpd_t(主体 type),Web 目录 /var/www/html 的类型是 httpd_sys_content_t(客体 type)。

  • SELinux 策略中预定义了规则:allow httpd_t httpd_sys_content_t:file read;(允许 httpd 进程读取 Web 目录的文件)。

  • 若将 /var/www/html 的类型改为 etc_t/etc 目录的类型),则 httpd 进程访问该目录时,SELinux 会拒绝(因为策略中没有 allow httpd_t etc_t:file read; 规则),即使 Linux 权限是 777 也无法访问。

/etc/selinux/targeted/contexts/users/目录下的guest_urootstaff_u等文件,对应的是SELinux 用户(SELinux User)—— 这是 SELinux 安全模型中用于身份标识的抽象概念,与 Linux 系统用户(如 /etc/passwd 中的用户)并非直接对应,而是通过映射关系关联(如 Linux 的 root 用户默认映射到 SELinux 的 root 用户)

查映射:用 semanage login -l 看 Linux 用户对应哪个 SELINUX 用户;

角色(system_runconfined_r 等)的作用是 “限制用户可切换的 type 范围”,但不直接决定进程能否访问资源。

[root@rhce ~]# semanage login -lLogin Name           SELinux User         MLS/MCS Range        Service__default__          unconfined_u         s0-s0:c0.c1023       *
root                 unconfined_u         s0-s0:c0.c1023       *
[root@rhce ~]# 
系统可以把LINUX用户识别成以下七种│   ├── users│   │   ├── guest_u│   │   ├── root│   │   ├── staff_u│   │   ├── sysadm_u│   │   ├── unconfined_u│   │   ├── user_u│   │   └── xguest_u
[root@rhce ~]# cat /etc/selinux/targeted/contexts/users/root 
system_r:crond_t:s0		unconfined_r:unconfined_t:s0 sysadm_r:cronjob_t:s0 staff_r:cronjob_t:s0 user_r:cronjob_t:s0“当进程处于 system_r:crond_t:s0 这个初始上下文时,允许它转换到后面列出的目标上下文(即切换到新的 role 和 type)”。
例如:crond_t 进程(定时任务进程)可以转换为 unconfined_t(无限制类型)或 cronjob_t(cron 任务专用类型),转换后以新的 type 运行

一、各 SELinux 用户的用途(典型场景)

每个 SELinux 用户文件定义了该用户在不同场景下的安全上下文转换规则,其核心作用是限制该用户能使用的角色和权限范围,具体如下:

SELinux 用户对应文件典型用途权限等级
rootroot对应 Linux 系统的 root 管理员,是 SELinux 中权限最高的用户,可切换到几乎所有角色(如 sysadm_runconfined_r),用于系统核心管理操作。最高(可执行敏感操作,如修改系统配置、管理服务)
unconfined_uunconfined_u对应 Linux 中 “无限制用户”(如普通用户但需较高权限),默认关联 unconfined_r(无限制角色),权限接近 root 但受部分限制,适合信任的普通用户。高(允许大部分操作,无需严格遵循 SELinux 类型限制)
sysadm_usysadm_u系统管理员专用 SELinux 用户,关联 sysadm_r(系统管理员角色),权限聚焦于系统管理(如启停服务、管理用户),但比 root 更受限(避免无差别高权限)。中高(仅允许系统管理相关操作)
staff_ustaff_u对应 “Staff 角色用户”(如中级运维人员),关联 staff_r 角色,权限介于管理员和普通用户之间,可执行部分管理操作(如 su 提权)但受严格限制。中等(有限的管理权限,核心操作需授权)
user_uuser_u普通受限用户,关联 user_r 角色,权限仅限于个人操作(如访问家目录、使用普通应用),无法执行系统管理操作,适合一般用户。低(仅允许个人级操作)
guest_uguest_u临时访客用户,权限极低,仅允许最基础的操作(如浏览网页、读取公共文件),无法修改系统或个人配置,适合临时登录场景。极低(严格限制,防止任何敏感操作)
xguest_uxguest_u图形界面下的访客用户,专为图形登录设计,权限与 guest_u 类似,但额外限制图形界面相关操作(如禁止修改桌面配置),适合公共电脑的临时使用。极低(图形场景的访客权限)

二、SELinux 用户与角色(Role)的区别

SELinux 中,“用户” 和 “角色” 是两个不同层级的安全概念,核心区别体现在 “范围” 和 “关联关系” 上:

维度SELinux 用户(User)SELinux 角色(Role)
定义抽象的身份标识,代表 “谁在操作”(如 rootuser_u)。操作权限的 “角色定位”,代表 “扮演什么角色”(如 sysadm_ruser_r)。
核心作用限制 “允许使用的角色范围”(一个用户可关联多个角色,但不能超出其允许的范围)。限制 “允许访问的类型(Type)范围”(一个角色关联多个类型,类型决定实际访问权限)。
层级关系上层概念,是角色的 “容器”:用户 → 允许的角色 → 允许的类型。中层概念,连接用户和类型:角色是用户与类型之间的桥梁。
举例staff_u(SELinux 用户)允许使用 staff_ruser_r 等角色,但不能使用 sysadm_r(除非授权)。staff_r(角色)允许访问 staff_tuser_t 等类型,但不能访问 sysadm_t(管理员专用类型)。
与 Linux 用户的关联Linux 用户需通过 /etc/selinux/targeted/logins 等文件映射到 SELinux 用户(如 Linux 的 root 映射到 SELinux 的 root)。角色不直接与 Linux 用户关联,而是通过 SELinux 用户间接关联(用户→角色→类型)。

三、总结

  • SELinux 用户是 “身份标签”,决定了用户能 “扮演哪些角色”;

  • 角色是 “权限标签”,决定了能 “访问哪些类型的资源”;

  • 两者通过 “用户→角色→类型” 的层级关系,共同实现 SELinux 的 “最小权限控制”:用户只能通过允许的角色,访问该角色允许的类型资源,避免权限滥用。

日常运维中,无需直接修改这些用户文件,而是通过 semanage login 命令管理 Linux 用户与 SELinux 用户的映射(如为普通 Linux 用户分配 staff_u),从而间接控制其权限范围。

3. SELinux 策略:规则的集合(“允许 / 拒绝” 的依据)

策略是 SELinux 的 “规则手册”,需讲清策略的类型、组成和作用:

(1)常见策略类型(RHEL 默认预装)

策略类型适用场景特点(教学重点)
targeted默认策略,仅对 “网络服务进程”(如 httpd、sshd、mysql)进行严格限制,对普通用户进程限制较少兼顾安全与易用性,适合生产环境(99% 场景用此策略)
minimum在 targeted 基础上,仅限制 “最关键的服务”(如 sshd),限制范围更小适合对性能要求高、安全需求低的场景
mls多级安全策略,基于 “安全级别(level)” 控制访问(如绝密文件只能被最高级进程访问)安全级别极高,适合军事、涉密场景,配置复杂

rhel9中SELinux默认的策略是targeted,如果要使用其他策略需要额外俺装相应的策略包:selinux-policy-minimumselinux-policy-mls

(2) SELinux配置文件

/etc/selinux/ 目录的核心逻辑是 “分层存储、按需加载”:

  1. 顶层文件(configsemanage.conf)控制全局模式;

  2. targeted 目录按 “策略开关 - 上下文映射 - 核心策略” 拆分配置,其中 contexts/files 是文件权限的关键,policy/policy.33 是访问规则的本体;

  3. 二进制文件(如 .binpolicy.33)用于 SELinux 高效加载,文本文件(如 file_contextsfile_contexts.local)用于用户配置修改。

日常运维中,修改最多的是 config(启用 / 禁用 SELinux)、file_contexts.local(自定义文件上下文),以及通过 semanage 命令间接修改 loginsseusers 等映射文件。

[root@shawn ~]# grep /usr/share/nginx/ /etc/selinux/targeted/contexts/files/file_contexts
/usr/share/nginx/html(/.*)?	system_u:object_r:httpd_sys_content_t:s0

一、顶层核心文件(/etc/selinux/ 目录下)

这两个文件是 SELinux 的 “全局控制入口”,决定 SELinux 的整体运行模式和管理规则。

文件名作用说明
configSELinux 主配置文件,控制 SELinux 的启用状态策略类型,关键配置项包括:- SELINUX:取值 enforcing(强制模式)、permissive(宽容模式)、disabled(禁用);- SELINUXTYPE:取值 targeted(默认,仅对关键服务生效)、mls(多级安全模式,更严格)。
semanage.confsemanage 命令(SELinux 策略管理工具)的配置文件,定义 semanage 的默认行为,如:- 策略模块的存储路径;- 是否启用审计日志;- 默认的策略类型(与 configSELINUXTYPE 对应)。

二、targeted 子目录(/etc/selinux/targeted/)

targeted 是 RHEL 9 默认的 SELinux 策略类型(对应 configSELINUXTYPE=targeted),该目录存储 targeted 策略的所有具体配置和数据,是 SELinux 策略的核心存储区。

1. 策略开关与映射文件(targeted 目录下直接文件)
文件名作用说明
booleans.subs_distSELinux 布尔值(开关)的 “分发版默认映射” 文件,定义系统预装布尔值的默认名称和关联规则,用户一般无需修改(自定义布尔值需通过 semanage boolean 命令)。
loginsSELinux 用户与 Linux 系统登录账号的映射配置文件,记录 “哪个 Linux 账号对应哪个 SELinux 用户”(如 root 对应 root SELinux 用户,普通用户默认对应 unconfined_u)。
setrans.confSELinux 翻译服务(setrans)的配置文件,用于将 SELinux 安全上下文(如 unconfined_u:unconfined_r:unconfined_t:s0)转换为人类易读的格式,主要用于日志显示和用户交互。
seuserslogins 功能类似,是 SELinux 用户与 Linux 账号的兼容映射文件,优先级低于 logins,主要用于兼容旧版本 SELinux 配置(现代系统优先读取 logins)。
2. contexts 子目录(/etc/selinux/targeted/contexts/)

存储 SELinux 安全上下文的映射规则,定义 “不同资源(文件、进程、端口、用户)应具备的安全上下文”,是 SELinux 访问控制的核心依据。

子文件 / 子目录作用说明
customizable_types定义 “可自定义安全类型” 的列表,即哪些 SELinux 类型(如 httpd_sys_content_t)允许用户通过 chconsemanage fcontext 命令修改,避免用户误改系统关键类型。
dbus_contexts为 D-Bus 服务(Linux 桌面 / 系统的进程通信机制)定义安全上下文规则,确保 D-Bus 进程间的通信符合 SELinux 策略,防止未授权进程通过 D-Bus 访问敏感服务。
default_contexts定义 “默认安全上下文”,包括用户登录时的默认上下文(如 unconfined_u:unconfined_r:unconfined_t:s0)、进程启动时的默认上下文,是 SELinux 上下文的 “基础模板”。
default_type指定系统默认的 SELinux 类型(default_t),用于 “未明确匹配其他上下文规则” 的资源(如临时文件、未知路径的文件),避免资源因无上下文而被 SELinux 直接拦截。
failsafe_context“故障安全” 上下文,当 SELinux 无法获取资源的正常上下文时(如配置错误、文件损坏),临时使用该上下文,确保系统不会因上下文缺失而完全无法运行。
files 子目录文件安全上下文的核心配置目录,详见下方 “files 子目录详解”。
initrc_context为系统初始化进程(init 或 systemd 启动阶段的进程)定义默认安全上下文,确保初始化过程中进程的访问权限符合 SELinux 策略。
lxc_contexts为 LXC(Linux 容器)相关进程和资源定义安全上下文,限制容器内进程对宿主机的访问,实现容器与宿主机的 SELinux 隔离。
openssh_contexts为 OpenSSH 服务(ssh 进程、sshd 守护进程)定义安全上下文规则,确保 SSH 服务的访问(如密钥文件读取、端口绑定)符合 SELinux 策略。
removable_context为可移动存储设备(U 盘、移动硬盘)定义默认安全上下文,防止外部存储中的恶意文件通过 SELinux 权限漏洞访问系统敏感资源。
securetty_types定义 “安全终端”(如 /dev/tty1/dev/console)对应的 SELinux 类型,限制只有特定类型的终端才能执行敏感操作(如 root 登录)。
sepgsql_contexts为 SE-PostgreSQL(PostgreSQL 数据库的 SELinux 增强)定义安全上下文,控制数据库进程对数据文件、端口的访问权限。
snapperd_contexts为 Snapper(Linux 系统快照工具)定义安全上下文,确保快照创建、恢复过程中对文件系统的操作符合 SELinux 策略。
systemd_contexts为 systemd 服务单元定义安全上下文规则,指定不同服务(如 nfs-server.servicehttpd.service)启动时的默认进程上下文(如 nfsd_thttpd_t)。
userhelper_contextuserhelper 工具(辅助普通用户执行特权操作的工具)定义安全上下文,限制 userhelper 只能执行预设的特权操作,防止权限滥用。
users 子目录存储不同 SELinux 用户(如 rootstaff_uuser_u)的默认上下文配置,每个文件对应一个 SELinux 用户,定义该用户登录后的默认角色(r)、类型(t)等。
virtual_domain_context为虚拟化域(如 KVM 虚拟机)定义安全上下文,限制虚拟机进程对宿主机资源的访问,实现虚拟化环境的 SELinux 隔离。
virtual_image_context为虚拟机镜像文件(如 .qcow2 文件)定义默认安全上下文,防止镜像文件被未授权进程修改或读取。
x_contexts为 X Window 系统(Linux 图形界面)的进程和资源(如窗口、显示设备)定义安全上下文,确保图形界面的访问符合 SELinux 策略。
files 子目录详解(/etc/selinux/targeted/contexts/files/)

该目录是 文件 / 目录安全上下文的核心映射区,决定 “特定路径的文件应具备哪种 SELinux 类型”(如 /var/www/html 对应 httpd_sys_content_t)。

文件名作用说明
file_contexts默认文件上下文映射文件,系统预装的 “路径 - 类型” 映射规则,覆盖绝大多数系统路径(如 /etc 对应 etc_t/home 对应 user_home_dir_t),是文件上下文的 “基础规则库”。
file_contexts.binfile_contexts二进制编译版本,由系统自动生成,SELinux 运行时优先加载二进制文件(加载速度更快),文本文件 file_contexts 是二进制文件的 “源配置”。
file_contexts.homedirs为用户家目录(如 /home/user/root)定义默认上下文映射,细化家目录内不同子路径的类型(如 /home/user/Documents 对应 user_home_t)。
file_contexts.homedirs.binfile_contexts.homedirs 的二进制编译版本,作用同 file_contexts.bin
file_contexts.local用户自定义文件上下文映射文件,优先级高于 file_contexts,用户通过 semanage fcontext 命令添加的自定义规则会写入此文件,用于覆盖默认映射(如自定义 /data/nfs 对应 nfs_t)。
file_contexts.subs文件路径 “替换规则” 文件,定义路径的简化别名(如将 /var/run 映射为 /run),确保 SELinux 能识别不同路径别名对应的上下文,避免因路径别名导致的规则失效。
file_contexts.subs_distfile_contexts.subs 的 “分发版默认文件”,系统预装的基础替换规则,用户自定义替换规则需修改 file_contexts.subs(而非此文件)。
media 子目录为媒体设备(如光盘、DVD)定义默认文件上下文,确保挂载媒体设备后,其内部文件的类型符合 SELinux 策略(如光盘文件对应 iso9660_t)。
3. policy 子目录(/etc/selinux/targeted/policy/)

存储 SELinux 核心策略文件,是 SELinux 访问控制规则的 “二进制编译结果”。

文件名作用说明
policy.33SELinux targeted 策略的核心二进制文件,包含所有 SELinux 访问控制规则(如 allow 允许规则、type_transition 类型转换规则),是 SELinux 运行时加载的 “策略本体”。- 后缀 33 是策略版本号,随系统更新可能变化(如 policy.34);- 无法直接用文本编辑器查看,需通过 sedispol 工具解析为文本规则。

4. SELinux 的工作模式:三种状态(控制严格程度)

SELinux 有三种工作模式,决定了规则的执行强度,是学员必须掌握的基础:

模式含义适用场景切换命令(临时)
Enforcing强制模式:严格执行 SELinux 策略,违反规则的操作会被拒绝并记录日志生产环境(默认模式,必须启用)setenforce 1
Permissive宽容模式:不拒绝违反规则的操作,但会记录日志(用于调试策略)新服务部署、排查 SELinux 相关问题时setenforce 0
Disabled禁用模式:完全关闭 SELinux(不加载策略,不记录日志)仅临时测试(不推荐生产环境,需重启生效)需修改 /etc/selinux/config 并重启
  • 关键区别Permissive 是 “记录不阻止”,Disabled 是 “不记录不阻止”;Disabled 需重启才能切换到其他模式,而 EnforcingPermissive 可通过 setenforce 实时切换。

三、SELinux 配置管理:掌握 “基本操作”

这部分是实操基础,学员需掌握 “查看状态、修改模式、管理安全上下文、调整布尔值” 等核心命令,为后续排错铺垫。

1. 查看 SELinux 状态

# 1. 查看整体状态(模式、策略类型等)
[root@shawn ~]# sestatus 
# 输出示例:
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   permissive
Mode from config file:          enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Memory protection checking:     actual (secure)
Max kernel policy version:      33
# 2. 查看当前工作模式(简洁)
getenforce
# 输出:Enforcing / Permissive / Disabled

2. 修改 SELinux 工作模式

(1)临时修改(立即生效,重启后失效)

[root@shawn ~]#setenforce 0  # 切换到 Permissive 模式(宽容)
[root@shawn ~]#setenforce 1  # 切换到 Enforcing 模式(强制)

(2)永久修改(需重启生效,修改配置文件)

[root@shawn ~]# vim /etc/selinux/config
# 核心配置:
# SELINUX=enforcing   # 永久启用强制模式(推荐)
# SELINUX=permissive # 永久启用宽容模式(调试)
# SELINUX=disabled   # 永久禁用(不推荐)# 修改后需重启系统生效
reboot

/etc/selinux/config文件内部:

3. 安全上下文管理(核心操作)

(1)查看安全上下文

# 查看文件/目录的安全上下文
[root@shawn ~]# ls -Z /var/www/html
# 输出示例:-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html
# 查看进程的安全上下文(主体 type)
[root@shawn ~]# ps -Z | grep httpd
# 输出示例:system_u:system_r:httpd_t:s0    1234 ?        00:00:00 httpd

2)修改安全上下文(两种方式)

方式 1:chcon 临时修改(重启或 restorecon 后失效)
# 格式:chcon [选项] 安全上下文 目标文件
# 示例:将 /data/web 的类型改为 httpd_sys_content_t(让 httpd 可访问)
chcon -t httpd_sys_content_t /data/web
方式 2:semanage 永久修改(写入策略,推荐)

chcon 是临时修改,semanage 会将修改保存到 SELinux 策略数据库,重启后不失效:

# 1. 安装 semanage 工具(默认可能未安装)
yum install policycoreutils-python-utils -y # 2. 永久修改目录的类型(-a 新增,-t 指定类型,-r 递归)
semanage fcontext -a -t httpd_sys_content_t "/data/web(/.*)?"
# 注:"/data/web(/.*)?" 表示匹配 /data/web 及所有子目录文件# 3. 应用修改(让策略生效)
restorecon -Rv /data/web  # -R 递归,-v 显示详细信息
  • 关键区别:chcon 适合临时测试,semanage + restorecon 适合永久配置(生产环境必用)。

4. 布尔值(Booleans)管理:快速调整策略开关

SELinux 预定义了大量 “布尔值”(开关),用于快速启用 / 禁用特定规则(无需修改安全上下文),是解决服务访问问题的常用手段。

SELinux 布尔值(Boolean)是 控制 SELinux 策略中 “条件性规则” 的开关变量,用于动态调整进程的权限范围。它们相当于 “策略中的配置项”,通过开启(on)或关闭(off),可以在不修改核心策略的前提下,灵活允许或禁止特定场景的访问行为(如允许 httpd 访问网络、执行脚本等)。

5. 端口标签管理:允许服务使用非标准端口

SELinux 不仅限制文件访问,还限制进程监听的端口(每个端口有 “端口类型” 标签)。例如,httpd 默认只能监听 http_port_t 类型的端口(如 80、443),若想让 httpd 监听 8080 端口,需将 8080 端口的类型改为 http_port_t

# 1. 查看当前允许 httpd 监听的端口类型及端口
semanage port -l | grep http_port_t
http_port_t                    tcp      80, 443, 488, 8008, 8009, 8443# 2. 永久添加 8080 端口到 http_port_t 类型
semanage port -a -t http_port_t -p tcp 8080# 移除端口标签   需 root 权限
semanage port -d -t http_port_t -p tcp 8080# 3. 验证添加结果
semanage port -l | grep http_port_t  # 此时会显示 8080

四、SELinux 实践操作:从 “理论” 到 “解决问题”

这是教学重点,通过 “服务访问故障排查” 案例,让学员掌握 “SELinux 导致的问题如何定位和解决”,避免遇到问题就禁用 SELinux。

在 SELinux 中,“主体(如进程)的 type 类型” 与 “客体(如文件、端口)的 type 类型” 是否 “匹配”,本质是指 SELinux 策略中是否存在允许主体 type 访问客体 type 的规则(即 allow 规则)。若存在允许规则,则认为 “类型匹配”(主体可合法访问客体);若不存在,则 “不匹配”(访问会被阻止)。

判断步骤:3 步确认类型是否匹配

步骤 1:获取主体(进程)的 type 类型

主体通常是进程,通过 ps -eZ 命令查看进程的 SELinux 上下文,其中 第三个字段即为主体的 type

示例:查看 httpd 进程的 type

ps -eZ | grep httpd

输出类似:

system_u:system_r:httpd_t:s0  1234 ?  00:00:00 httpd

→ 主体(httpd 进程)的 type 是 httpd_t

步骤 2:获取客体(资源)的 type 类型

客体可以是文件、目录、端口等,根据资源类型使用不同命令查看,第三个字段即为客体的 type

客体类型查看命令示例(获取 type)说明
文件 / 目录ls -Z /var/www/html查看 /var/www/html 的 type
端口semanage port -l | grep http查看 http 相关端口的 type

示例:查看 /var/www/html 文件的 type

ls -Z /var/www/html

输出类似:

unconfined_u:object_r:httpd_sys_content_t:s0 index.html

→ 客体(文件)的 type 是 httpd_sys_content_t

步骤 3:检查策略中是否存在允许访问的规则

通过 sesearch 工具(需安装 setools-console 包)查询 SELinux 策略中是否有允许 “主体 type 访问客体 type” 的规则。

核心语法:

sesearch -A -s 主体type -t 客体type -c 资源类别
  • -A:仅显示 allow 规则(允许访问的规则);

  • -s:指定主体 type(如 httpd_t);

  • -t:指定客体 type(如 httpd_sys_content_t);

  • -c:指定资源类别(如 file 表示文件,port 表示端口,process 表示进程等)。

[root@shawn ~]# sesearch -A -s httpd_t -t httpd_sys_content-t
httpd_sys_content-t is not a valid type attribute

SELinux 策略规则的通用格式为:allow 主体类型 客体类型:类别 { 权限列表 };

  • 主体类型:被允许操作的进程类型(通常对应某个服务,如 httpd_t 是 Apache 进程的类型)。

  • 客体类型:被访问的资源(文件 / 目录等)的 SELinux 类型(如 httpd_sys_content_t 是 Apache 网页内容的默认类型)。

  • 类别:资源的类型(如 dir 表示目录,lnk_file 表示符号链接文件)。

  • 权限列表:允许主体对客体执行的具体操作(如 read 表示读取)。

第一条规则解析:allow httpd_t httpd_sys_content_t:dir { ioctl lock read };

  • 主体类型httpd_t→ 对应 Apache 服务进程(httpdapache2)的 SELinux 类型。

  • 客体类型httpd_sys_content_t→ SELinux 中专门用于标记 “Apache 可访问的网页内容目录 / 文件” 的类型(如 /var/www/html 目录默认类型)。

  • 类别dir→ 表示客体是 “目录”(而非文件或符号链接)。

  • 权限列表{ ioctl lock read }

    • read:允许读取目录内容(如列出目录下的文件)。

    • lock:允许对目录加锁(如防止并发操作冲突)。

    • ioctl:允许执行 I/O 控制命令(如获取 / 设置目录的底层属性)。

规则作用:允许 Apache 进程(httpd_t)对标记为 httpd_sys_content_t 的目录执行读取、加锁和 I/O 控制操作(确保 Apache 能正常访问网页目录结构)。

第二条规则解析:allow httpd_t httpd_sys_content_t:lnk_file { getattr read };

  • 主体类型httpd_t(同上,Apache 进程)。

  • 客体类型httpd_sys_content_t(同上,Apache 可访问的内容类型)。

  • 类别lnk_file→ 表示客体是 “符号链接文件”(软链接)。

  • 权限列表{ getattr read }

    • read:允许读取符号链接本身指向的目标路径。

    • getattr:允许获取符号链接的属性(如创建时间、权限等元数据)。

规则作用:允许 Apache 进程(httpd_t)读取标记为 httpd_sys_content_t 的符号链接文件,以及获取其属性(确保 Apache 能跟随网页目录中的软链接访问目标资源)。

实验1:SELinux端口限制实践

步骤1:确保nginx服务正在运行

[root@shawn ~]# systemctl is-active nginx.service 
active

步骤2:查看nginx进程的上下文

[root@shawn ~]# ps -axZ | grep nginx
system_u:system_r:httpd_t:s0       3774 ?        Ss     0:00 nginx: master process /usr/sbin/nginx
system_u:system_r:httpd_t:s0       3775 ?        S      0:00 nginx: worker process
system_u:system_r:httpd_t:s0       3776 ?        S      0:00 nginx: worker process
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 4013 pts/1 S+   0:00 grep --color=auto nginx

步骤3:停止nginx服务并查看状态

[root@shawn ~]# systemctl stop nginx.service 
[root@shawn ~]# systemctl is-active nginx.service 
inactive

步骤4:查看SELinux允许nginx侦听端口

[root@shawn ~]# semanage port -l |grep http
http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
http_cache_port_t              udp      3130
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t            tcp      5988
pegasus_https_port_t           tcp      5989

步骤5:修改nginx服务的监听端口为82

[root@shawn ~]# vim /etc/nginx/nginx.conf
listen 82;

步骤6:再次启动httpd服务

[root@shawn ~]# systemctl restart nginx.service 
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.

步骤7:查看SELinux日志

[root@shawn ~]# grep "nginx" /var/log/audit/audit.log | grep "denied"
type=AVC msg=audit(1763035565.317:420): avc:  denied  { getattr } for  pid=3697 comm="nginx" path="/web/index.html" dev="dm-0" ino=34868111 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=1
type=AVC msg=audit(1763035565.317:421): avc:  denied  { read } for  pid=3697 comm="nginx" name="index.html" dev="dm-0" ino=34868111 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=1
type=AVC msg=audit(1763035565.317:421): avc:  denied  { open } for  pid=3697 comm="nginx" path="/web/index.html" dev="dm-0" ino=34868111 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=1
type=AVC msg=audit(1763038243.675:436): avc:  denied  { name_bind } for  pid=4093 comm="nginx" src=82 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:reserved_port_t:s0 tclass=tcp_socket permissive=1
type=AVC msg=audit(1763038327.672:443): avc:  denied  { name_bind } for  pid=4116 comm="nginx" src=82 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:reserved_port_t:s0 tclass=tcp_socket permissive=1
type=AVC msg=audit(1763038354.752:449): avc:  denied  { getattr } for  pid=4122 comm="nginx" path="/web/index.html" dev="dm-0" ino=34868111 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=1
type=AVC msg=audit(1763038354.752:450): avc:  denied  { read } for  pid=4122 comm="nginx" name="index.html" dev="dm-0" ino=34868111 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=1
type=AVC msg=audit(1763038354.752:450): avc:  denied  { open } for  pid=4122 comm="nginx" path="/web/index.html" dev="dm-0" ino=34868111 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=1
type=AVC msg=audit(1763038396.458:457): avc:  denied  { name_bind } for  pid=4157 comm="nginx" src=82 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:reserved_port_t:s0 tclass=tcp_socket permissive=0

SELinux 阻止 Nginx 进程的原因是:Nginx 进程(类型 httpd_t)尝试绑定 82 端口(类型 reserved_port_t),但 SELinux 策略中没有 “允许 httpd_treserved_port_t 类型的 tcp_socket 执行 name_bind 权限” 的规则

具体来说:

  • 82 端口属于 1-1024 特权端口,SELinux 默认将其标记为 reserved_port_t 类型;

  • Nginx 进程的类型被错误标记为 httpd_t(正常应为 nginx_t),而 httpd_t 类型的进程默认没有绑定 reserved_port_t 端口的权限(name_bind);

  • 因此 SELinux 在强制模式下直接拒绝了绑定操作,导致 Nginx 无法启动或监听 82 端口。

步骤8:配置SELinux允许nginx侦听端口82

[root@shawn ~]# semanage port -a -t http_port_t -p tcp 82
# 添加 82 到 http_port_t
[root@shawn ~]# semanage port -l | grep http
http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
http_cache_port_t              udp      3130
http_port_t                    tcp      82, 80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t            tcp      5988
pegasus_https_port_t           tcp      5989

步骤9:重启nginx

[root@shawn ~]# systemctl restart nginx.service 

实验2:SELinux类型限制实践-管理安全上下文

步骤1:临时修改SELinux模式为Permissive

[root@shawn ~]# setenforce 0
[root@shawn ~]# getenforce 
Permissive
[root@shawn ~]#

步骤2:创建nginx主页面

[root@shawn ~]# mkdir /web
mkdir: 无法创建目录 “/web”: 文件已存在
[root@shawn ~]# echo 123 > /web/index.html

步骤3:修改nginx配置

[root@shawn ~]# vim /etc/nginx/nginx.conf

步骤4:重新加载配置并验证

[root@shawn ~]# systemctl restart nginx.service 

步骤5:修改SELinux模式为Enforcing

[root@shawn ~]# setenforce 1
[root@shawn ~]# getenforce 
Enforcing

步骤6:查看SELinux日志

[root@shawn ~]# systemctl restart nginx.service 
[root@shawn ~]# curl 192.168.60.128:80
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.20.1</center>
</body>
</html>
[root@shawn ~]# grep "nginx" /var/log/audit/audit.log | grep "denied"
type=AVC msg=audit(1763177272.774:107): avc:  denied  { getattr } for  pid=4903 comm="nginx" path="/web/index.html" dev="dm-0" ino=34868111 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0

这条日志的关键是 “类型不匹配”:

  • 进程类型(httpd_t)和文件类型(default_t)都不符合 Web 服务的 SELinux 配置规范;

  • 解决的核心思路是 “让文件类型适配进程类型”(或修正进程类型),让 SELinux 策略中的允许规则生效。

日常排查时,只要看到 avc: denied { getattr } + 文件路径 + 类型为 default_t,优先修正文件的 SELinux 类型即可快速解决。

步骤7:修改index.html类型

[root@shawn ~]# semanage fcontext -a -t httpd_sys_content_t /web/index.html
[root@shawn ~]# ll -Z /web/index.html 
-rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 4 11月 15 11:22 /web/index.html
[root@shawn ~]# restorecon -R -v /web/index.html 
Relabeled /web/index.html from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0

步骤8:再次验证实验结果

[root@shawn ~]# curl 192.168.60.128:80
123

实验3:SELinux类型限制实践(setroubleshoot应用)

步骤1:安装、配置nginx的资源目录是/home/redhat

[root@shawn ~]# systemctl restart nginx.service 
[root@shawn ~]# vim /etc/nginx/conf.d/test.conf
server {listen  84;root /home/redhat;
}
[root@shawn ~]# echo "home redhat" > /home/redhat/index.html
[root@shawn ~]# chmod 755 /home/redhat
[root@shawn ~]# chmod 644 /home/redhat/index.html

                                                   

步骤2:重启Nginx,发现失败

[root@shawn ~]# systemctl restart nginx.service 
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.
[root@shawn ~]# grep "nginx" /var/log/audit/audit.log | grep "denied"
type=AVC msg=audit(1763177860.469:119): avc:  denied  { name_bind } for  pid=5049 comm="nginx" src=84 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:reserved_port_t:s0 tclass=tcp_socket permissive=0

步骤3:配置SELinux允许nginx侦听端口84、修改目标资源类型

[root@shawn ~]# semanage port -a -t http_port_t -p tcp 84
[root@shawn ~]# semanage fcontext -a -t httpd_sys_content_t "/home/redhat(/.*)?"
[root@shawn ~]# restorecon -R -v /home/redhat/
Relabeled /home/redhat from unconfined_u:object_r:user_home_dir_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/redhat/.bash_logout from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/redhat/.bash_profile from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/redhat/.bashrc from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/redhat/index.html from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
[root@shawn ~]# systemctl start nginx
[root@shawn ~]# curl 192.168.60.128:84
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.20.1</center>
</body>
</html>

下载并启用setroubleshoot

[root@shawn ~]# yum install setroubleshoot -y
[root@shawn ~]# systemctl start setroubleshootd.service

步骤4:

[root@shawn ~]# ausearch -m AVC -c nginx --raw | audit2allow -M nginx_access_home
******************** IMPORTANT ***********************
To make this policy package active, execute:semodule -i nginx_access_home.pp[root@shawn ~]# semodule -i nginx_access_home.

ausearch -m AVC -c nginx --raw从 SELinux 审计日志(/var/log/audit/audit.log)中,筛选出与 Nginx 相关的 “访问拒绝事件(AVC)”,并以原始格式输出。 核心是 “抓出 Nginx 被 SELinux 拦下来的操作”(比如 “想读文件被拒”“想进目录被拒”)。

audit2allow -M nginx_access_home接收前一段的拒绝日志,自动分析 “谁(Nginx 进程)需要什么权限”,生成两个文件:

  1. nginx_access_home.te:策略源码文件(人类可读,记录具体允许规则);

  2. nginx_access_home.pp:编译后的二进制策略包(可直接加载到 SELinux)。

→ 核心是 “把‘被拒绝的操作’变成‘允许的规则’”。

步骤5:

[root@shawn ~]# curl http://192.168.60.128:84
home redhat

http://www.dtcms.com/a/613359.html

相关文章:

  • 安装k8s过程中涉及知识点梳理
  • 公司网站建设费用如何做账英语可以做推广的亲子类网站
  • 【2025】Java 从入门到实战:核心特性全解析(方法、类与对象、多态三大特性及关键字thissuper)附带代码案例
  • FSMC-TFTLCD显示实验(1)
  • Node.js 实现 Stripe 支付的简单示例
  • Claude、Agent与Copilot协作生成Angular应用
  • 建行广东茂名茂南支行:积极走进会展商圈,助力金融赋能消费提振
  • LDO(Low Dropout Regulator)是什么?
  • 专门做win7系统的网站免费金融发布网站模板
  • 网络安全:SQL 注入:SQLmap
  • UI设计公司审美积累|APP界面从风格到功能的设计智慧
  • 分布式专题——57 如何保证MySQL数据库到ES的数据一致性
  • 厦门建站公司哪家好wordpress 虚拟商城
  • 分布式专题——56 微服务日志采集与分析系统实战
  • 团购网站自个做中国最好室内设计公司排名榜
  • 如何使用WPF做工控主页
  • 深入探讨HarmonyOS分布式剪贴板:技术原理与开发实践
  • USB3.0PHY介绍
  • Three.js的阴影相关实现路径
  • WPF转换器机制
  • SLAM中的非线性优-3D图优化之轴角在Opencv-PNP中的应用(三)
  • 如何用WPF做工控设置界面
  • ✨WPF编程进阶【7.2】:动画类型(附源码)
  • 建设网站的安全性介绍深圳seo优化排名推广
  • 上海迈诺网站建设东莞专业做网站的公司有哪些
  • 深度学习中的激活函数全解析:该选哪一个?
  • MySQL复盘总结
  • 对于多方安全计算的中止安全的理解
  • 西游记路线图:12-39,大唐到乌鸡国,幕后boss标注
  • 【学习笔记】DiffFNO: Diffusion Fourier Neural Operator