SELinux 安全模块详解

SELinux 安全模块详解

SELinux(Security-Enhanced Linux)是目前 Linux 内核中最强大、最严格的强制访问控制(MAC)机制。它由美国国家安全局开发并开源,已成为 Red Hat 系发行版(RHEL、CentOS、Rocky、AlmaLinux、Fedora)和部分其他发行版的默认安全组件。

与传统权限模型(chmod/chown + owner/group/other)最大的不同在于:即使你是 root 用户,进程也必须严格遵守 SELinux 策略定义的访问规则。这使得即使存在配置错误、提权漏洞或恶意代码,攻击面也会被极大压缩。

一、SELinux 的核心价值与防护能力

SELinux 最擅长的防护场景包括:

  • 即使服务被提权,也无法读取 /etc/shadow、修改系统关键文件
  • Web 服务进程即使被 RCE,也很难写 webshell 到其他目录或执行反弹 shell
  • 数据库服务即使存在 SQL 注入导致的文件写入,也无法访问其他数据库文件或家目录
  • 防止横向移动:一个被攻陷的低权限服务难以访问高权限服务的文件/端口/进程
  • 限制零日漏洞的破坏半径:即使漏洞允许任意代码执行,也受限于进程的域(domain)权限

一句话总结:SELinux 把“出了漏洞还能做什么”变成了“出了漏洞也做不了太多”

二、三种运行模式与切换方式

SELinux 有三种运行状态:

  1. enforcing(强制模式) 严格执行策略,违规访问直接被拒绝并记录审计日志。这是生产推荐模式。
  2. permissive(宽松模式) 记录所有违规访问,但不实际拒绝。这是调试和迁移时的最佳状态
  3. disabled(完全关闭) 内核不加载 SELinux 策略模块,性能损失最小,但失去全部 MAC 保护。强烈不建议长期使用

常用切换命令(无需重启):

Bash
# 查看当前模式
getenforce
sestatus | grep "Current mode"

# 临时切换(调试最常用)
setenforce 0    # → permissive
setenforce 1    # → enforcing

永久修改需编辑配置文件 /etc/selinux/config 或 /etc/sysconfig/selinux,然后重启。

三、安全上下文(Security Context)——理解 SELinux 的钥匙

每个文件、目录、进程、套接字、端口等对象都有一个 SELinux 安全上下文,格式通常是:

user:role:type[:level]

其中最关键的是 type 字段(以 _t 结尾的进程类型,或文件类型)。

典型例子:

  • 进程:httpd_t(Apache/Nginx 主进程域)
  • 静态网页文件:httpd_sys_content_t
  • 可写上传目录:httpd_sys_rw_content_t
  • SSH 服务进程:sshd_t
  • 用户家目录文件:user_home_t
  • 普通用户运行的进程:unconfined_t(几乎无限制)

上下文决定“谁(进程类型)能访问什么(文件/端口类型)”。

最常见的权限问题根源:文件上下文不对 → 即使 chmod 777 也访问失败。

四、策略类型对比

主流发行版默认使用两种策略:

策略类型保护范围复杂度生产推荐场景
targeted只限制网络服务(httpd、mysqld、sshd等)中等99% 的企业生产环境
mls全系统严格多级安全(带敏感度级别 s0–s15)极高军工、政府高密级系统

查看当前策略:

Bash
sestatus | grep "Loaded policy name"

五、核心操作思路与常用模式

生产中最常遇到的操作模式只有三类:

  1. 文件/目录上下文修复(占比最高)

    Bash
    # 一次性修复(最常用)
    restorecon -Rv /path/to/your/dir
    
    # 永久自定义上下文(强烈推荐)
    semanage fcontext -a -t httpd_sys_content_t "/custom/web(/.*)?"
    restorecon -Rv /custom/web
  2. 允许/禁止某类行为(布尔开关)

    Bash
    # 查看所有布尔
    getsebool -a | grep http
    
    # 允许 httpd 发起网络连接(常见需求)
    setsebool -P httpd_can_network_connect on
    
    # 允许 httpd 访问家目录
    setsebool -P httpd_enable_homedirs on
  3. 处理拒绝日志并快速放行

    Bash
    # 查看最近拒绝
    ausearch -m avc -ts recent
    
    # 一键生成允许规则并安装
    ausearch -m avc -ts recent | audit2allow -M mycustom
    semodule -i mycustom.pp

六、典型问题与正确处理路径

问题类型典型表现正确处理顺序
403 Forbidden(web)ls -Z 显示类型不对restorecon → semanage fcontext → setsebool
mysqld 无法启动自定义数据目录权限拒绝semanage fcontext -t mysqld_db_t “/new/data(/.*)?” → restorecon
Nginx 监听 8080 失败端口上下文不对semanage port -a -t http_port_t -p tcp 8080
容器挂载目录权限异常SELinux 标签丢失挂载时加 :z(共享)或 :Z(私有)标签
服务启动失败但日志无 Permission deniedaudit.log 有 AVC denied先 permissive 模式启动 → ausearch → audit2allow

七、生产环境实用建议

  1. 永远保持 enforcing + targeted 模式
  2. 所有自定义目录/端口一律通过 semanage 管理
  3. 定期查看审计日志(ausearch -m avc),不要让拒绝日志堆积
  4. 容器环境(Docker/Podman/Kubernetes)必须理解 :z / :Z 标签含义
  5. 新服务器上线后第一件事:sestatus 检查是否 enforcing
  6. 迁移老系统时先 permissive 运行几天,收集拒绝日志再逐步收紧

结语

SELinux 的学习曲线确实陡峭,但一旦掌握核心思维(上下文 + 布尔 + 审计日志),它会变成你最可靠的安全底座之一。

记住一句话:“SELinux 拒绝的不是你权限不够,而是你‘身份类型’不允许做这件事”

下次遇到“权限明明够却打不开”的诡异问题,先执行 ls -Z 和 ausearch -m avc -ts recent,而不是直接 setenforce 0。大多数时候,30 秒就能找到根因。

希望这篇更聚焦概念和思路的版本,能让你对 SELinux 的理解更清晰、操作更从容。

Telegram
Telegram@IDCSELL