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 加固。