12. SELinux 加固 Linux 安全

发布于:2025-08-07 ⋅ 阅读:(17) ⋅ 点赞:(0)

12. SELinux 加固 Linux 安全

SELinux 介绍

SELinux 概述

可以把 SELinux 想象成 Linux 系统里的 “超级门卫”,比普通权限管理(如 chmod)更严格,专门管 “谁能碰什么东西,能做什么操作”。

举个例子:
就像公司里,财务室(某个文件 / 目录)只能让财务(某个进程)进,而且财务只能用财务软件(特定程序)查看账本(特定文件),不能用普通记事本打开,更不能把账本拿到别的部门(其他目录)。

  • 即使你知道财务室钥匙(有 root 权限),如果 SELinux 没允许,你也进不去;
  • 就算财务人员(进程)拿到了钥匙,想做超出权限的事(比如用记事本改账本),SELinux 也会直接拦下。

简单说,SELinux 给每个 “东西”(文件、目录)和 “做事的”(进程)都贴了 “身份标签”,规定死 “谁能用什么身份做什么事”,哪怕黑客拿到部分权限,也很难越界搞破坏。

它就像给系统加了一层 “铁栅栏”,默认严格,按需放宽,是 Linux 安全的 “第二道防线”。

SELinux 模式
  • enforcing 模式: SELinux强制执行访问控制规则。 在强制模式下,如果规则没有明确允许访问,则拒绝访问,并写入日志。此模式是默认模式。
  • Permissive 模式:SELinux 加载策略并处于活动状态,但不强制执行访问控制规则,⽽是记录访问违规。此模式有助于对应用和规则进行测试和故障排除。
  • disable 模式:完全关闭 SELinux。不拒绝任何SELinux违规,不予记录。

更改 SELinux 默认模式

[root@server ~ 16:26:27]# vim /etc/selinux/config
SELINUX=enforcing
SELINUXTYPE=targeted
#查看当前模式
[root@server ~ 16:37:21]# getenforce 
Enforcing

在启动时通过将向内核传递参数来设置SELinux 模式

  • enforcing=1,设置强制模式。
  • enforcing=0,设置许可模式。
  • selinux=0,来彻底禁用 SELinux。
  • selinux=1,启用 SELinux(当设置enforcing参数是,该参数可以省略)。

控制文件 SELinux 上下文

新文件默认 SELinux 上下文

新文件通常从父目录继承其SELinux上下文,从而确保它们具有适当的上下文。

[root@server ~ 16:56:43]# touch /tmp/yy
[root@server ~ 17:02:39]# ls -ldZ /tmp/ /tmp/yy
drwxrwxrwt. root root system_u:object_r:tmp_t:s0       /tmp/
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 /tmp/yy
[root@server ~ 17:02:58]# cp /tmp/yy /root/yy

[root@server ~ 17:03:53]# ls -ldZ /tmp /tmp/yy /root /root/yy
dr-xr-x---. root root system_u:object_r:admin_home_t:s0 /root
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /root/yy
drwxrwxrwt. root root system_u:object_r:tmp_t:s0       /tmp
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 /tmp/yy
[root@server ~ 17:04:02]# cp  -a /tmp/yy /root/yy-a
[root@server ~ 17:04:27]# ls -ldZ /tmp /tmp/yy /root /root/yy*
dr-xr-x---. root root system_u:object_r:admin_home_t:s0 /root
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /root/yy
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 /root/yy-a
drwxrwxrwt. root root system_u:object_r:tmp_t:s0       /tmp
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 /tmp/yy
[root@server ~ 17:04:55]# mv /tmp/yy /root/yy-mv
[root@server ~ 17:05:25]# ls -ldZ /tmp /root /root/yy*
dr-xr-x---. root root system_u:object_r:admin_home_t:s0 /root
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /root/yy
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 /root/yy-a
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 /root/yy-mv
drwxrwxrwt. root root system_u:object_r:tmp_t:s0       /tmp

这段操作就像 SELinux 这个 “标签管理员” 在处理文件的 “身份卡片”,不同操作会让文件的 “身份标签” 发生有趣的变化,咱们用 “搬家贴标签” 来类比:

  1. 初始状态
    • /tmp 目录是 “临时文件区”,标签是 tmp_t(像 “临时存放处” 的牌子);
    • /tmp 里创建的 yy 文件,自动贴上 user_tmp_t 标签(相当于 “临时文件专属卡”)。
  2. 普通复制(cp /tmp/yy /root/yy
    • 把文件从 “临时区” 搬到 “管理员家”(/root 目录,标签 admin_home_t,像 “管理员书房” 的牌子);
    • SELinux 会给新文件换标签,改成目标目录的默认标签 admin_home_t(就像把 “临时文件卡” 换成 “书房文件卡”,入乡随俗)。
  3. -a 复制(cp -a /tmp/yy /root/yy-a
    • -a 是 “完全复制”,包括文件的 “身份标签”;
    • 所以新文件 yy-a 依然带着原来的 user_tmp_t 标签(相当于搬家时特意保留了 “临时文件卡”,没换成 “书房卡”)。
  4. 移动文件(mv /tmp/yy /root/yy-mv
    • 移动和复制不同,文件只是换了位置,没重新创建;
    • 所以标签保持原样 user_tmp_t(就像把文件从 “临时区” 挪到 “书房”,但没换卡,还带着原来的 “临时文件卡”)。

总结:

SELinux 的标签规则像 “搬家规矩”:

  • 普通复制(cp):按新家规矩换标签;
  • -a 复制或移动(mv):保留原标签,不按新家规矩改。

这就是为什么同样是把 /tmp/yy 弄到 /root 下,三个文件会有不同的标签

设置文件 SELinux 上下文

设置文件上下文命令

  • chcon 命令,直接更改文件SELinux上下文。但是,它不会将上下文更改保存到 SELinux 上下文数据库中。系统下一次对所有文件进行 relabel 操作时,将导致该上下文恢复。它对于测试和实验很有用。

  • restorecon 命令,根据 SELinux上下文数据库中规则,恢复文件SELinux上下文。原先通过 chcon命令所做的更改,将失效。

[root@server ~ 17:05:46]# mkdir /www
[root@server ~ 17:06:39]# ls -Zd /www
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /www
[root@server ~ 17:06:48]# chcon -t httpd_sys_content_t /www
[root@server ~ 17:07:26]# ls -Zd /www
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 /www
[root@server ~ 17:07:28]# restorecon -v /www
restorecon reset /www context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:default_t:s0
[root@server ~ 17:07:46]# ls -Zd /www
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /www

这段操作就像在 SELinux 这个 “超级门卫” 面前 “贴标签又被撕” 的过程

  1. 创建 /www 目录:相当于新建了一个 “房间”,SELinux 自动给它贴了个默认标签 default_t(类似 “杂物间” 标签)。
  2. chcon -t httpd_sys_content_t /www:你手动把标签改成了 httpd_sys_content_t(相当于把 “杂物间” 标签换成 “网站文件专用间”),这样 Apache 进程(网站服务器)就被允许访问这个目录了。
  3. restorecon -v /www: SELinux 的 “标签管理员” 来了,它查了查 “建筑规范”(系统默认的标签规则),发现 /www 按规矩应该是 default_t,于是又把你改的标签撕了,恢复成默认标签(就像物业按规定纠正了错误的房间用途标识)。

semanage fcontext 命令用于管理SELinux上下文数据库中规则,restorecon 命令根据这些规则恢复文件上下文。semanage fcontext命令使用扩展的正则表达式指定路径和文件名。比较常见的扩展正则表达式(/.*)?,表示随意匹配/后面接任意数量字符,递归匹配文件夹下的子文件和子文件夹。

  • chcon 命令,直接更改文件SELinux上下文。但是,它不会将上下文更改保存到 SELinux 上下文数据库中。系统下一次对所有文件进行 relabel 操作时,将导致该上下文恢复。它对于测试和实验很有用。

  • restorecon 命令,根据 SELinux上下文数据库中规则,恢复文件SELinux上下文。原先通过 chcon命令所做的更改,将失效。

配置 web 站点主目录

[root@server ~ 17:14:27]# echo hello world from server > /www/index.html
[root@server ~ 17:15:52]# ls -Zd /www
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /www

#允许访问
[root@server ~ 17:17:06]# chcon -t httpd_sys_content_t /www/index.html
#恢复后又不能访问
[root@server ~ 17:17:57]# restorecon -Rv /www
restorecon reset /www/index.html context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:default_t:s0

# 添加默认规则
[root@server ~ 17:21:00]# semanage fcontext -a -t httpd_sys_content_t '/www(/.*)?'


# 恢复文件上下文,仍可以访问
[root@server ~ 17:28:59]# restorecon -Rv /www/
restorecon reset /www context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
restorecon reset /www/index.html context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0

#启动httpd服务
[root@server ~ 17:29:49]# systemctl restart httpd
#编辑配置文件
[root@server ~ 17:07:53]# vim /etc/httpd/conf/httpd.conf
# 注释122 行DocumentRoot,在122行后,添加如下内容:
# DocumentRoot "/var/www/html"
DocumentRoot "/www"
<Directory "/www">
    AllowOverride None
    # Allow open access:
    Require all granted
</Directory>

#重启

#查看并验证
[root@server ~ 17:30:18]# ls -dZ /www
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 /www

控制端口 SELinux 上下文

端口 SELinux 上下文

**SELinux还可以对端口标记。**当某个进程希望侦听端口时, SELinux将检查是否允许与该进程相关联的标签绑定该端口标签。 这可以阻止恶意服务控制本应由其他网络服务使用的端口。

在 targeted 策略中:

  • 端口 22/TCP ,具有标签 ssh_port_t
  • 端口 80/TCP 和 443/TCP ,具有标签 http_port_t
# 查看端口标记
[root@server ~ 09:36:36]# semanage port -l | grep http_port_t
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t            tcp      5988
# 添加端口标记
[root@server ~ 09:43:28]# semanage port -a -t http_port_t -p tcp 18020
[root@server ~ 09:44:22]# semanage port -l | grep 18020
http_port_t                    tcp      18020, 80, 81, 443, 488, 8008, 8009, 8443, 9000
# 删除端口标记
[root@server ~ 09:44:36]# semanage port -d -t http_port_t -p tcp 18020
[root@server ~ 09:44:55]# semanage port -l | grep 18020

示例:配置 web 站点监听端口

[root@server ~ 09:44:57]# vim /etc/httpd/conf/httpd.conf
# 修改原先的 Listen 80 为 Listen 18020
Listen 18020
# 重启服务
[root@server ~ 09:46:39]# systemctl disable firewalld.service --now
[root@server ~ 09:47:09]# systemctl restart httpd
#报错(13)Permission denied: could not bind to address 0.0.0.0:18020,核心原因是SELinux 安全策略限制。SELinux 默认只允许 httpd 服务使用预定义的端口(如 80、443 等),自定义端口18020未被授权。
[root@server ~ 09:47:44]# systemctl status httpd.service  |cat |grep per

# 配置端口
[root@server ~ 09:48:55]# semanage port -a -t http_port_t -p tcp 18020
[root@server ~ 09:49:20]# semanage port -l | grep 18020
http_port_t                    tcp      18020, 80, 81, 443, 488, 8008, 8009, 8443, 9000

# 重启服务并访问
[root@server ~ 09:49:28]# semanage port -lC
SELinux 端口类型                   协议       端口号

http_port_t                    tcp      18020
[root@server ~ 09:49:41]# systemctl restart httpd

控制 SELinux 布尔值

SELinux 布尔值

SELinux 布尔值是可更改SELinux策略行为的开关,可以启用和禁用。

如果把 SELinux 比作一栋有严格门禁的大楼,那布尔值就像是每个房间门口的「智能开关」。

平时这些开关默认处于「关」的状态 —— 比如 “允许快递员进客厅”“允许维修工进厨房” 这些权限都是锁死的。但大楼管理员(就是系统管理员)可以根据需要,随时按一下开关:

  • 想让 Web 服务器(httpd)能访问外部数据库?那就把「httpd_can_network_connect」这个开关拨到「开」,相当于给它开了 “出大门” 的权限。
  • 想让 Samba 服务共享用户的个人文件夹?就把「samba_enable_home_dirs」打开,等于允许 “访客进卧室”。

这些开关的特点是:按一下立刻生效,不用重启大楼(系统),也不用重新装修(修改核心策略)。而且每个开关都对应一个具体场景,不会像改端口那样 “牵一发而动全身”,既灵活又安全。

简单说,SELinux 布尔值就是一堆 “即开即用” 的权限小开关,专门解决那些 “偶尔需要开个小口子” 的场景。

SELinux 布尔值是可更改SELinux策略行为的开关,可以启用和禁用。

# 查看SELinux布尔值
[root@server ~ 09:53:02]# getsebool -a |grep httpd_enable_homedirs
httpd_enable_homedirs --> off

# 设置SELinux布尔值
[root@server ~ 10:21:35]# setsebool httpd_enable_homedirs=1
[root@server ~ 10:22:04]# getsebool -a |grep httpd_enable_homedirs
httpd_enable_homedirs --> on
#etsebool httpd_enable_homedirs=1或者on或者true
#setsebool httpd_enable_homedirs=0或者off或者false

示例:允许 httpd 访问用户家目录

# 删除原先自定义的 SELinux 布尔值
[root@server ~ 10:22:07]# semanage boolean -D
[root@server ~ 10:23:00]# vim /etc/httpd/conf.d/userdir.conf
# 修改以下两个参数
    UserDir enabled
	UserDir public_html
# 重启服务
[root@server ~ 10:24:27]# systemctl restart httpd
[root@server ~ 10:24:45]# 登出

# 设置权限
[yy@server ~ 10:24:50]$ mkdir public_html
[yy@server ~ 10:25:37]$ echo 'welcome to home' > public_html/index.html
[yy@server ~ 10:25:47]$ ll /home/
总用量 0
drwx------. 3 yy yy 102 86 10:25 yy
[yy@server ~ 10:25:56]$ chmod o+x /home/yy/

未启用布尔值访问

在这里插入图片描述

启用布尔值访问

[root@server ~ 10:28:02]# setsebool httpd_enable_homedirs=1

在这里插入图片描述

SELinux 问题处理思路
  1. 确定是否是 SELinux 引起的。
  2. 在做调整前,首先考虑 SELinux 是否正确的阻止了访问。例如web服务器尝试访问/home目录,如果web的内容不是用户发布的,那么发生阻止信号是正确的阻止。如果这个访问是被允许的,参考下面步骤。
  3. 最常见的 SELinux 问题是不正确的文件上下文。当文件是另外一个地方创建的,然后移动到新的地方,而新的地方需要新的上下文。在大多数情况,执行restorecon可以修复这个问题。这种修复问题方式对系统其他部分安全影响非常小。
  4. 另外一个问题可能是布尔值设置不当导致拒绝访问。例如ftpd_anon_write布尔值控制匿名ftp用户是否可以上传文件。如果如需匿名用户上传文件,需要打开这个布尔值。调整布尔值需要小心,因为对系统影响范围比较大。
  5. 还有可能是 端口上下文不匹配。
  6. 还有可能是 SELinux bug。
    止信号是正确的阻止。如果这个访问是被允许的,参考下面步骤。
  7. 最常见的 SELinux 问题是不正确的文件上下文。当文件是另外一个地方创建的,然后移动到新的地方,而新的地方需要新的上下文。在大多数情况,执行restorecon可以修复这个问题。这种修复问题方式对系统其他部分安全影响非常小。
  8. 另外一个问题可能是布尔值设置不当导致拒绝访问。例如ftpd_anon_write布尔值控制匿名ftp用户是否可以上传文件。如果如需匿名用户上传文件,需要打开这个布尔值。调整布尔值需要小心,因为对系统影响范围比较大。
  9. 还有可能是 端口上下文不匹配。
  10. 还有可能是 SELinux bug。

网站公告

今日签到

点亮在社区的每一天
去签到