SELinux 是什么

Security-Enhanced Linux——NSA 开发的强制访问控制(MAC)系统,1998 开源,2003 进入 Linux 内核。

传统 DAC(自主访问控制):所有者决定谁能访问
SELinux MAC(强制访问控制):内核根据策略决定,所有者也改不了

实际效果:即使 root 跑某个程序,SELinux 也能限制它——大幅缩小被攻破后的爆炸半径。

主要见于 RHEL / CentOS / Fedora / Rocky——默认启用。Ubuntu 用 AppArmor(思路类似,配置不同)。

三种模式

# 看当前模式
getenforce
# Enforcing | Permissive | Disabled
模式 行为
Enforcing 拒绝违反策略 + 记日志(生产默认)
Permissive 不拒绝,但记日志(调试用)
Disabled 完全关闭(不推荐)

切换:

# 临时(重启失效)
sudo setenforce 0      # Permissive
sudo setenforce 1      # Enforcing

# 永久(改配置 + 重启)
sudo vim /etc/selinux/config
# SELINUX=enforcing | permissive | disabled

上下文(Context):SELinux 的核心

每个文件 / 进程 / 端口都有一个安全上下文

ls -Z /var/www/html/index.html
# unconfined_u:object_r:httpd_sys_content_t:s0  index.html
#  ↑           ↑          ↑                     ↑
#  user        role       type                  level

最重要的是 type——决定能干什么 / 谁能碰。

例:

  • httpd_sys_content_t — Apache/Nginx 能读
  • mysqld_db_t — MySQL 能读写
  • ssh_home_t — SSH 相关家目录

常见 SELinux"惊喜"

场景:把网站文件放非默认目录

mkdir /srv/web
cp index.html /srv/web/
# 配置 nginx root /srv/web

curl http://localhost
# → 403 Forbidden

原因:/srv/web 的 SELinux type 不是 httpd_sys_content_t,nginx 没权限读。

修复:

# 1. 看默认类型
ls -Zd /srv/web

# 2. 改类型
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/web(/.*)?"
sudo restorecon -Rv /srv/web

# 3. 验证
ls -Z /srv/web

场景:服务监听非标准端口

# 让 sshd 监听 2222
sudo vim /etc/ssh/sshd_config
# Port 2222
sudo systemctl restart sshd
# → 启动失败

原因:2222 端口的 SELinux 上下文不允许 ssh 用。

修复:

sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo systemctl restart sshd        # 现在能启动

故障排查流程

服务因 SELinux 失败时:

# 1. 临时设 permissive 看是否 SELinux 引起
sudo setenforce 0
# 试操作
# 如果 OK → 100% SELinux 问题

# 2. 看 audit 日志
sudo ausearch -m AVC -ts recent

# 3. 用 audit2why 看为什么被拒
sudo audit2why < /var/log/audit/audit.log | tail

# 4. 用 audit2allow 生成允许规则(谨慎!)
sudo audit2allow -a -M mymodule
sudo semodule -i mymodule.pp

# 5. 测试完恢复
sudo setenforce 1

不要直接 disable SELinux 来"解决"问题——这是放弃额外的安全层。先理解为什么被拒,再针对性放权。

几个常用命令

sestatus                          # 完整状态
getenforce / setenforce           # 模式
ls -Z file                        # 看上下文
chcon -t TYPE file                # 临时改类型(重启 restorecon 会还原)
semanage fcontext -a -t TYPE PATH # 改默认类型(永久)
restorecon -Rv DIR                # 应用上下文
semanage port -l | grep http      # 看 http 占哪些端口
getsebool -a | grep httpd         # 看 httpd 相关布尔开关
setsebool -P httpd_can_network_connect on    # 启用布尔

布尔开关(最简单的策略调整)

很多场景都有现成的"开关":

# 让 httpd 能连数据库
sudo setsebool -P httpd_can_network_connect_db on

# 让 httpd 能连任意网络
sudo setsebool -P httpd_can_network_connect on

# 让 nfs 共享
sudo setsebool -P use_nfs_home_dirs on

-P = 持久(写进策略);不加 -P 重启失效。

SELinux vs AppArmor

特性 SELinux AppArmor
默认 RHEL 系 Ubuntu / Debian
模型 标签(label-based) 路径(path-based)
复杂度
灵活度

两者目的一样,配置截然不同——选哪个看发行版。

下一篇:SSH 加固。