SELinux:比root还霸道的权限管家
2026/8/4 15:56:54 网站建设 项目流程

管理 SELinux 安全性:权限都给了还是拒绝,原来是它在"管闲事"

开头

学 Linux 之前,我一直以为权限管理就是chmod那套:rwx三个字母,owner / group / others 三组人,把 755、644 背熟就完事了。直到这周讲 SELinux,我才发现自己理解的"安全"有多天真。

老师上课第一句就是:“就算你是 root,权限也不一定能访问。” 我当场就懵了——root 不是最大吗?怎么还有管得住 root 的东西?

那节课我的脑子里全是浆糊:SELinux 到底是个啥?为什么文件明明是 755 权限,nginx 还是给我 403?还有网上教程动不动就让人先执行一句setenforce 0,但没人跟我说清楚它到底干了什么、为什么"重启就失效"。

正好上一篇博客写重置 root 密码时碰到过touch /.autorelabel,当时只知道照着敲,这周学完 SELinux 总算把那一串串概念串起来了。这篇就按我自己的理解顺序写一遍,把上课记的那几个知识点展开成能看懂的笔记。


一、先搞清楚:为什么有了 chmod 还要 SELinux?

DAC 和 MAC 的区别

以前学的 chmod 那套权限,叫自主访问控制(DAC)——DiscretionaryAccessControl。它有个致命问题:权限由文件所有者自己说了算。只要文件属于你,你想给谁读就给谁读;更关键的是,root 拥有一切权限,绕过了所有权限检查。

SELinux 用的叫强制访问控制(MAC)——MandatoryAccessControl。它跟 DAC 完全不同:

  • 权限策略由系统统一制定,不是文件所有者决定的
  • root 也会被限制,不是"超级用户就能为所欲为"
  • 遵循最小权限原则,每个进程只给够用的权限

我当时的理解:DAC 是"文件主人说了算",MAC 是"系统说了算"。进程想碰资源,DAC 先查一遍 rwx,过了之后 SELinux 还要按策略再查一遍,两道关都过才放行

所以网上的 CentOS 教程第一句就是setenforce 0,其实就是嫌第二道关麻烦——但它把最关键的安全防线给关了,而且很多人不知道这只是临时的。

SELinux 是怎么保护的?

SELinux 给每个进程、文件、端口都打上一个**安全上下文(security context)标签。访问发生时,SELinux 把进程的标签和客体的标签放进策略(policy)**里比对,不满足策略就直接拒绝,连 root 都不给面子。


二、三种模式:Enforcing / Permissive / Disabled(对应课堂第 4 题)

SELinux 有三种模式,这是我这周记得最牢的:

模式getenforce 输出行为
强制模式Enforcing不符合策略就拒绝并记录日志
宽容模式Permissive不拒绝,只记录告警日志
禁用Disabled完全不管

查看当前模式:

getenforce# Enforcing

临时切换(不写配置文件,重启失效):

setenforce0# 切到宽容模式(Permissive)setenforce1# 切回强制模式(Enforcing)

课堂第 4 题的答案:setenforce 0临时把 SELinux 切成宽容模式。它不阻止违规访问,但会把告警记到日志里;重启后就恢复原样

要想永久改,得编辑配置文件:

vim/etc/selinux/config
SELINUX=enforcing # 可选 enforcing / permissive / disabled SELINUXTYPE=targeted # 默认策略,还有 minimum 和 mls

改完配置文件要重启才完全生效,当前运行模式还得靠setenforce手动切。

踩坑:我第一次做实验时执行了setenforce 0,发现挺好使,就以为系统一直这样了。结果第二天开机,getenforce一看,又变回Enforcing了。找半天才想起老师说的"临时"两个字。


三、安全上下文:那个冒号分隔的标签

这是这章最核心的概念。安全上下文就是附加在进程、文件、端口上的安全标签,格式是四段冒号分隔:

用户:角色:类型:级别 unconfined_u:object_r:httpd_sys_content_t:s0
  • 用户:SELinux 用户,不是系统用户(如unconfined_usystem_u
  • 角色:如object_r(客体)、system_r(系统进程)
  • 类型最关键的一段,如httpd_sys_content_t
  • 级别:MLS/MCS 的级别,一般是s0,多类别时会有c0.c1023

查看文件和进程的上下文:

ls-Z/etc/passwd# system_u:object_r:etc_t:s0 /etc/passwdps-eZ|grepsshd# system_u:system_r:sshd_t:s0-s0:c0.c1023 ...id-Z# unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

SELinux 策略就是靠比对上下文(主要是类型)来判断访问权限的。进程是httpd_t类型,它就只能访问类型匹配的内容(比如httpd_sys_content_t),想碰/etc/shadowshadow_t)就会被拦。

我当时把这个理解成"工作证对工牌":进程带着工作证,文件贴着工牌,门卫(策略)只放行对得上的。


四、让 httpd 能读 /custom 目录

这是课堂的实操题,也是 RHCSA 常见的考点:把 /custom 目录设为网站内容目录,让 httpd 能读

第一次我直接chmod 777 /custom,心想权限都给了肯定行。结果刷新页面还是 403。看日志才知道,是SELinux 拦的——/custom 目录的文件默认是default_t类型,httpd 根本不让碰。

正确做法分两步:先定规则,再打标签

第一步:定义文件上下文规则

semanage fcontext-a-thttpd_sys_content_t"/custom(/.*)?"

这条命令的含义:给/custom目录以及里面所有文件(/.*)?这个正则就是匹配子目录和文件)定义一条规则——将来的标签类型是httpd_sys_content_t

semanage fcontext只是写规则,并不会立刻改文件标签。第一次我没搞清楚这步,执行完就去访问,还是 403。

第二步:用 restorecon 按规则打标签

restorecon-Rv/custom

restorecon按规则重新设置文件的上下文-R递归处理目录里所有内容,-v显示过程。

查看当前有哪些规则:

semanage fcontext-l|grepcustom

查看标签是否打上:

ls-Zd/custom# system_u:object_r:httpd_sys_content_t:s0 /custom

chcon 和 restorecon 的区别

除了restorecon,还有个chcon能直接改标签:

chcon-thttpd_sys_content_t /custom/index.html

chcon改的是"当前标签",是临时的,跟规则无关,之后一次restorecon就会被打回原形。所以规范做法永远是用semanage fcontext定规则 +restorecon打标签。

记法semanage fcontext像"立规矩",restorecon像"照规矩办事",chcon像"临时手动改"。

注意:semanage 可能没装

RHEL9 上执行semanage可能报command not found,需要装个包:

dnfinstall-ypolicycoreutils-python-utils

五、布尔值:开关式策略(Bonus)

课堂上顺带讲的,我觉得挺有用。SELinux 有些策略是"开关式"的,叫布尔值(boolean),比如"httpd 能不能联网"“能不能访问家目录”。

getsebool-a|grephttpd setsebool-Phttpd_can_network_connect on

踩坑setsebool如果不加-P重启后就还原了。加-P才是永久(persistent)。这跟setenforce 0一个套路——临时和永久的区别,真的是这章最容易踩的坑。


六、被拒了怎么排查

遇到"权限明明给了还是拒绝",先别急着chmod 777,先看是不是 SELinux 拦的。

SELinux 的拒绝记录在审计日志里:

# 最近被拒绝的记录ausearch-mavc-tsrecent# 直接 grep 日志grep"denied"/var/log/audit/audit.log

装了 setroubleshoot-server 的话,还能让它直接给建议:

dnfinstall-ysetroubleshoot-server sealert-a/var/log/audit/audit.log

sealert会给出类似"你想让 httpd 访问某个目录,可以执行semanage fcontext ..."的建议,对新手特别友好。


我踩过的坑合集(考前必看)

说明解决方法
chmod 777不看 SELinux权限给了还是 403先查 audit.log,八成是 SELinux 拦的
setenforce 0重启失效以为永久生效永久要改/etc/selinux/config
semanage命令不存在提示 command not founddnf install policycoreutils-python-utils
只写了规则忘了 restorecon执行semanage fcontext后直接访问restorecon -Rv按规则打标签
restorecon忘了-R只改了目录本身,子文件没变-R递归
mv 过来的文件还是 403mv 保留原来的上下文restorecon重新打标签
setsebool忘加-P重启后开关还原永久要加-P
把 SELINUX 改成 disabled想改回 enforcing 后登录不了/卡住改回 enforcing 重启,等它自动 autorelabel 扫完

关于"mv 还是 403":cp出来的新文件会继承目标目录的默认上下文,但mv是移动,文件的标签原封不动跟着走。所以把一个 html 从/homeuser_home_t)mv 到/var/www/html,标签还是user_home_t,httpd 照样读不了——必须restorecon一下。这是我猜了半天才发现的。


需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询