SELinux介绍
SELinux概述
文件权限管理文件去权限控制了哪些用户或用户组访问哪些特定文件,但没有限定用户访问文件的方式。
Security(安全) Enhanced (增强)Linux(SELinux)是一个额外的系统安全层,主要目标是防止已遭泄露的系统服务访问用户数据。
SELinux强制执行一组访问规则,明确定义进程和资源之间允许的操作。每个进程,文件,目录和端口都具有专门的安全标签,称为SELinux上下文。上下文是一个名称,SELinux策略使用来确定某个进程能否访问文件、目录或端口。
web服务器守护进程类型是httpdexect
web服务器的网页类型是httpdsyscontent_t
web服务器的端口类型是httpdportt
基本原理
SELinux默认策略允许apache进程访问在/var/www/html文件夹下的文件和文件夹,以及其他一些具有httpdsyscontent_t上下文的文件夹,禁止访问具有其他不匹配标签的目录。
命令选项-Z
许多处理文件的命令都有-Z选项,用于显示SELinux的标签
ls -Zl /home
ls -Zl /var/www/html
SELinux模式
enforcing模式:selinux强制执行访问控制规则,此模式为默认模式。
permissive模式:selinux加载策略处于活动状态,但不强制执行访问控制规则,记录访问违规。
disable模式:完全关闭selinux,不拒绝任何selinux违规,不予记录。
查看当前模式
getenforce
更改模式
setenforce 0 | premissive #切换为允许模式
setenforce 1 | enforcing #切换为强制模式
更改SELinux默认模式
vim /etc/selinux/config
#将SELINUX的参数修改为enforcing
在启动时可以通过向内核传递参数设置SELinux模式:
enforcing=1,强制模式
enforcing=0,许可模式
selinux=0,彻底禁用selinux
selinux=1,启用selinux,后面可以跟参数
对照实验
通过grub菜单rd.break修改root密码,修改之后再次启动时在内核中设置打开selinux,由于通过rd.break修改root密码的时候,系统还挂载在/sysroot下,还没有到识别标签的步骤,所以修改后识别不到原来的标签,导致输入正确的root密码也无法登录,普通用户登录也会受到影响。
重启进入内核,修改密码后创建/.autorelabel文件,让系统在下次启动时自动重新标记所有文件的标签。
控制文件SELinux上下文
新文件通常从父目录继承selinux标签。
touch /tmp/robin
ll -dZ /tmp /tmp/robin
cp /tmp/robin /root/robin
ll -Zd /tmp /tmp/robin /root /root/robin
#当/tmp/robin被复制到/root下时,标签发生改变,变成其父目录的标签
cp -a /tmp/robin /root/robin-a
ll -Zd /tmp /tmp/robin /root /root/robin*
#此时/root目录下的robin-a的标签依然为/tmp的标签
mv /tmp/robin /root/robin-mv
ll -Zd /tmp /root /root/robin*
设置文件SELinux上下文
chcon命令
直接更改文件selinux标签,但是不会将标签保存到selinux标签库中,系统下一次进行relabel操作时,就会导致标签恢复。
restorecon命令
根据标签库中规则,恢复文件selinux标签,之前chcon命令修改的将会失效。
mkdir /www
ll -Zd /www
drwxr-xr-x. 2 root root unconfined_u:object_r:default_t:s0 24 6月 19 12:34 /www
chcon -t httpd_sys_connect_t /www
ll -Zd /www
drwxr-xr-x. 2 root root unconfined_u:object_r:httpd_sys_connect_t:s0 24 6月 19 12:34 /www
restorecon -v /www
ll -Zd /www
drwxr-xr-x. 2 root root unconfined_u:object_r:default_t:s0 24 6月 19 12:34 /www
semanager fcontext命令
用于管理selinux标签库中规则,restorecon命令根据规则恢复标签,使用扩展的正则表达式指定路径和文件名,比如(/.*)?,表示随意匹配/后面接任意数量字符,递归匹配文件夹下和子文件夹
echo hello world > /www/index.html
ll -Zd /www/index.html
#安装semanager工具
dnf -y install policycoreuils-python-units
#添加默认规则
semanage fcontext -a -t httpd_sys_content_t '/www(/.*)?'
#-a 添加新记录 -t 类型为 '/www(/.*)?' - 这是一个正则表达式,匹配目录/www及其下的所有文件和子目录(/.*)
-rw-r--r--. 1 root root unconfined_u:object_r:httpd_sys_content_t:s0 10 6月 19 11:09 /www/index.html
#只查看非默认策略
semanage fcontext -lC #C-custom自定义
SELinux fcontext 类型 上下文
/www(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
#恢复文件标签
restorecon -Rv /www/ #递归 显示过程
#删除默认规则
semanage fcontext -d -t httpd_sys_content_t '/www(/.*)?'
配置web站点主目录
mkdir /www
echo hello world > /www/index.html
semanage fcontext -a -t httpd_sys_content_t '/www(/.*)?'
restorecon -Rv /www/ #立刻应用该规则
#安装httpd
systemctl enable httpd --now
vim /etc/httpd/conf.d/vhost.conf #主配置文件目录为/etc/httpd/conf/httpd.conf 手动创建的配置文件存放在/etc/httpd/conf.d
<VirtualHost *:80>
DocumentRoot "/www"
ServerName www.robin.cloud
<Directory "/www">
AllowOverride None
# Allow open access:
Require all granted
</Directory>
</VirtualHost>
#重启服务
systemctl restart httpd
curl http://server.robin.cloud
curl: (7) Failed to connect to www.robin.cloud port 80: 拒绝连接
ll -Zd /www/
drwxr-xr-x. 2 root root unconfined_u:object_r:httpd_sys_content_t:s0 24 6月 19 12:34 /www/
ll -Zd /www/index.html
-rw-r--r--. 1 root root unconfined_u:object_r:httpd_sys_content_t:s0 10 6月 19 11:09 /www/index.html
ll -Zd /var/www/html/index.html
-rw-r--r--. 1 root root unconfined_u:object_r:httpd_sys_content_t:s0 13 6月 19 11:13 /var/www/html/index.html
ss -tulnp | grep httpd
tcp LISTEN 0 511 *:18020 *:* users:(("httpd",pid=3066,fd=4),("httpd",pid=3065,fd=4),("httpd",pid=3064,fd=4),("httpd",pid=3052,fd=4))
#发现问题 httpd监听为18020端口,修改配置文件
vim /etc/httpd/conf/httpd.conf
systemctl restart httpd
#重启服务后再次访问,正常
curl http://www.robin.cloud
hello world
控制端口SELinux标签
selinux还可以对端口进行标记,当某个进程希望侦听端口时,selinux将会检查端口标签。
在targeted策略中:
端口22/TCP,具有标签sshportt
端口80/TCP和443/TCP具有标签httpportt
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
#添加端口标签
semanage port -a -t http_port_t -p tcp 18020
#-a 增加新记录 -t类型为 -p协议为
semanage port -l | grep 18020
http_port_t tcp 18020, 80, 81, 443, 488, 8008, 8009, 8443, 9000
#删除端口标记
semanage port -d -t http_port_t -p tcp 18020
配置web站点监听端口
vim /etc/httpd/conf/httpd.conf
#将监听端口修改为18020
systemctl restart httpd
#配置端口
semanage port -a -t http_port_t -p tcp 18020
semanage port -l | grep http_port_t
http_port_t tcp 18020, 80, 81, 443, 488, 8008, 8009, 84
pegasus_http_port_t tcp 5988
#只查看改动标签
semanage port -lC
SELinux 端口类型 协议 端口号
http_port_t tcp 18020
vim /etc/httpd/conf.d/vhost.conf
<VirtualHost *:18020>
DocumentRoot "/www"
ServerName www.robin.cloud
<Directory "/www">
AllowOverride None
# Allow open access:
Require all granted
</Directory>
</VirtualHost>
#修改配置文件后务必重启服务
systemctl restart httpd
curl http://www.robin.cloud:18020
hello world
控制SELinux布尔值
selinux布尔值是可以更改selinux策略行为的开关,可以开启或禁用
getsebool -a | grep httpd_enable_homedirs
httpd_enable_homedirs --> on
#设置selinux布尔值
setsebool httpd_enable_homedirs=0
getsebool -a | grep httpd_enable_homedirs
httpd_enable_homedirs --> off
#持久化设置布尔值
setsebool -P httpd_enable_homedirs=0 #-P选项持久化保存
允许httpd访问用户家目录
vim /etc/httpd/conf.d/userdir.conf
#编辑 Apache HTTP 服务器的用户目录配置文件
UserDir enabled
UserDir public_html #默认用户目录名称
#修改两条参数
systemctl restart httpd
su - robinkool
mkdir public_html
echo "welcome to robin's home" > public_html/index.html
cat public_html/index.html
welcome to robin's home
chmod o+x /home/robinkool/ #家目录至少可执行(允许进入)
#未启用布尔值访问
curl http://www.robin.cloud:18020/~robinkool/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>
#启用布尔值访问
setsebool httpd_enable_homedirs=1
curl http://www.robin.cloud:18020/~robinkool/
welcome to robin's home
vim etc/httpd/conf.d/userdir.conf
#确保userdir=enabled
semanage fcontext -d -t httpd_user_content_t"/home/robinkool/public_html(/.*)?"
#删除之前的自定义规则
restorecon -Rv /home/robinkool
#恢复基于默认规则管理
getsebool -a | grep httpd_enable_homedirs
#确保布尔值是否启用
systemctl restart httpd
#确保修改配置文件后系统重启
#恢复 SELinux标签
chcon -R -t user_home_dir_t /home/robinkool/public_html
#检查配置文件
vim /etc/httpd/conf.d/userdir.conf
#重启 Apache
systemctl restart httpd
#测试访问
curl http://www.robin.cloud:18020/~robinkool/
SELinux问题处理思路
首先确定是否是由selinux引起,通过setenforce=1或setenforce=0来排除起因,如果确定是由于selinux引起,可以通过一下思路一一排除:
1.文件的标签发生改变,除了mv和cp -a的移动会保留原来的标签外,其余移动都会导致标签发生改变,可以restorecon -Rv来恢复。
2.排除文件标签后,可以考虑是否是布尔值设置的问题,使用getsebool -a |来对对应的服务进行排查是否启用布尔值。
3.排除布尔值影响后,还有端口标签的影响,semanage port -l | grep ,通过抓取对应端口标签来查看是否符合目录标签要求。以及ss -lnutp查看端口使用来一一对应。
setroubleshoot-server软件包
setroubleshoot-server软件包中的setroubleshoot服务提供了诊断工具,当selinux拒绝某一操作时,会在安全日志中记录消息,发送到/var/log/message中。
dnf -y install httpd setroubleshoot-server
setsebool httpd_enable_homedirs=0
tail -f /var/log/messages
Jun 19 22:40:52 server systemd[1]: Started The Apache HTTP Server.
Jun 19 22:41:04 server httpd[6381]: Server configured, listening on: port 18020
Jun 19 22:58:56 server dbus-daemon[1758]: avc: received policyload notice (seqno=13)
Jun 19 22:58:56 server dbus-daemon[1478]: avc: received policyload notice (seqno=13)
Jun 19 22:58:56 server dbus-daemon[1442]: avc: received policyload notice (seqno=13)
Jun 19 22:58:56 server setsebool[6764]: The httpd_enable_homedirs policy boolean was changed to 0 by root
Jun 19 22:58:56 server /usr/libexec/gdm-wayland-session[1478]: dbus-daemon[1478]: [session uid=42 pid=1478] Reloaded configuration
Jun 19 22:58:56 server dbus-daemon[1442]: [session uid=42 pid=1442] Reloaded configuration
Jun 19 22:58:56 server dbus-daemon[1046]: [system] Reloaded configuration
Jun 19 22:58:56 server /usr/libexec/gdm-wayland-session[1758]: dbus-daemon[1758]: Reloaded configuration
如需要完整的 SELinux 信息,请运行 sealert -l 8d373a05-410e-4622-bcf6-f8b6266e9bfa
sealert -l 8d373a05-410e-4622-bcf6-f8b6266e9bfa
SELinux is preventing /usr/sbin/httpd from read access on the 文件 index.html.
***** 插件 public_content (32.5 置信度) 建议 *************************************
如果你想要治疗 index.html作为公共内容
Then 则需要在 index.html 将标签改为 public_content_t 或 public_content_rw_t。
Do
# semanage fcontext -a -t public_content_t 'index.html'
# restorecon -v 'index.html'
***** 插件 catchall_boolean (32.5 置信度) 建议 ***********************************
如果你想 allow httpd to enable homedirs
Then 必须启用 'httpd_enable_homedirs' 布尔值告知 SELinux 此情况。
Do
setsebool -P httpd_enable_homedirs 1
***** 插件 catchall_boolean (32.5 置信度) 建议 ***********************************
如果你想 allow httpd to unified
Then 必须启用 'httpd_unified' 布尔值告知 SELinux 此情况。
Do
setsebool -P httpd_unified 1
***** 插件 catchall (4.5 置信度) 建议 ********************************************
如果你相信 httpd应该允许_BASE_PATH read 访问 index.html file默认情况下。
Then 应该将这个情况作为 bug 报告。
可以生成本地策略模块以允许此访问。
Do
暂时允许此访问权限执行:
# ausearch -c 'httpd' --raw | audit2allow -M my-httpd
# semodule -X 300 -i my-httpd.pp
更多信息:
源环境 (Context) system_u:system_r:httpd_t:s0
目标环境 unconfined_u:object_r:httpd_user_content_t:s0
目标对象 index.html [ file ]
源 httpd
源路径 /usr/sbin/httpd
端口 <Unknown>
主机 server
源 RPM 软件包 httpd-2.4.37-64.module+el8.10.0+1717+030a9fed.x86_
64
目标 RPM 软件包
SELinux 策略 RPM selinux-policy-targeted-3.14.3-139.el8_10.noarch
本地策略 RPM selinux-policy-targeted-3.14.3-139.el8_10.noarch
Selinux 已启用 True
策略类型 targeted
强制模式 Permissive
主机名 server
平台 Linux server 4.18.0-553.el8_10.x86_64 #1 SMP Fri
May 24 13:05:10 UTC 2024 x86_64 x86_64
警报计数 18
第一个 2025-06-19 22:20:30 CST
最后一个 2025-06-19 23:01:15 CST
本地 ID 8d373a05-410e-4622-bcf6-f8b6266e9bfa
原始核查信息
type=AVC msg=audit(1750345275.801:340): avc: denied { read } for pid=6385 comm="httpd" name="index.html" dev="dm-2" ino=157 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_user_content_t:s0 tclass=file permissive=1
type=AVC msg=audit(1750345275.801:340): avc: denied { open } for pid=6385 comm="httpd" path="/home/robinkool/public_html/index.html" dev="dm-2" ino=157 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_user_content_t:s0 tclass=file permissive=1
type=SYSCALL msg=audit(1750345275.801:340): arch=x86_64 syscall=openat success=yes exit=EFAULT a0=ffffff9c a1=7f0a1000a678 a2=80000 a3=0 items=0 ppid=6381 pid=6385 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm=httpd exe=/usr/sbin/httpd subj=system_u:system_r:httpd_t:s0 key=(null)
Hash: httpd,httpd_t,httpd_user_content_t,file,read
#直接粘贴给出的命令就可以解决问题
控制SELinux布尔值
selinux布尔值是可以更改selinux策略行为的开关,可以开启或禁用
getsebool -a | grep httpd_enable_homedirs
httpd_enable_homedirs --> on
#设置selinux布尔值
setsebool httpd_enable_homedirs=0
getsebool -a | grep httpd_enable_homedirs
httpd_enable_homedirs --> off
#持久化设置布尔值
setsebool -P httpd_enable_homedirs=0 #-P选项持久化保存
允许httpd访问用户家目录
vim /etc/httpd/conf.d/userdir.conf
#编辑 Apache HTTP 服务器的用户目录配置文件
UserDir enabled
UserDir public_html #默认用户目录名称
#修改两条参数
systemctl restart httpd
su - robinkool
mkdir public_html
echo "welcome to robin's home" > public_html/index.html
cat public_html/index.html
welcome to robin's home
chmod o+x /home/robinkool/ #家目录至少可执行(允许进入)
#未启用布尔值访问
curl http://www.robin.cloud:18020/~robinkool/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>
#启用布尔值访问
setsebool httpd_enable_homedirs=1
curl http://www.robin.cloud:18020/~robinkool/
welcome to robin's home
vim etc/httpd/conf.d/userdir.conf
#确保userdir=enabled
semanage fcontext -d -t httpd_user_content_t"/home/robinkool/public_html(/.*)?"
#删除之前的自定义规则
restorecon -Rv /home/robinkool
#恢复基于默认规则管理
getsebool -a | grep httpd_enable_homedirs
#确保布尔值是否启用
systemctl restart httpd
#确保修改配置文件后系统重启
#恢复 SELinux标签
chcon -R -t user_home_dir_t /home/robinkool/public_html
#检查配置文件
vim /etc/httpd/conf.d/userdir.conf
#重启 Apache
systemctl restart httpd
#测试访问
curl http://www.robin.cloud:18020/~robinkool/
SELinux问题处理思路
首先确定是否是由selinux引起,通过setenforce=1或setenforce=0来排除起因,如果确定是由于selinux引起,可以通过一下思路一一排除:
1.文件的标签发生改变,除了mv和cp -a的移动会保留原来的标签外,其余移动都会导致标签发生改变,可以restorecon -Rv来恢复。
2.排除文件标签后,可以考虑是否是布尔值设置的问题,使用getsebool -a |来对对应的服务进行排查是否启用布尔值。
3.排除布尔值影响后,还有端口标签的影响,semanage port -l | grep ,通过抓取对应端口标签来查看是否符合目录标签要求。以及ss -lnutp查看端口使用来一一对应。
setroubleshoot-server软件包
setroubleshoot-server软件包中的setroubleshoot服务提供了诊断工具,当selinux拒绝某一操作时,会在安全日志中记录消息,发送到/var/log/message中。
dnf -y install httpd setroubleshoot-server
setsebool httpd_enable_homedirs=0
tail -f /var/log/messages
Jun 19 22:40:52 server systemd[1]: Started The Apache HTTP Server.
Jun 19 22:41:04 server httpd[6381]: Server configured, listening on: port 18020
Jun 19 22:58:56 server dbus-daemon[1758]: avc: received policyload notice (seqno=13)
Jun 19 22:58:56 server dbus-daemon[1478]: avc: received policyload notice (seqno=13)
Jun 19 22:58:56 server dbus-daemon[1442]: avc: received policyload notice (seqno=13)
Jun 19 22:58:56 server setsebool[6764]: The httpd_enable_homedirs policy boolean was changed to 0 by root
Jun 19 22:58:56 server /usr/libexec/gdm-wayland-session[1478]: dbus-daemon[1478]: [session uid=42 pid=1478] Reloaded configuration
Jun 19 22:58:56 server dbus-daemon[1442]: [session uid=42 pid=1442] Reloaded configuration
Jun 19 22:58:56 server dbus-daemon[1046]: [system] Reloaded configuration
Jun 19 22:58:56 server /usr/libexec/gdm-wayland-session[1758]: dbus-daemon[1758]: Reloaded configuration
如需要完整的 SELinux 信息,请运行 sealert -l 8d373a05-410e-4622-bcf6-f8b6266e9bfa
sealert -l 8d373a05-410e-4622-bcf6-f8b6266e9bfa
SELinux is preventing /usr/sbin/httpd from read access on the 文件 index.html.
***** 插件 public_content (32.5 置信度) 建议 *************************************
如果你想要治疗 index.html作为公共内容
Then 则需要在 index.html 将标签改为 public_content_t 或 public_content_rw_t。
Do
# semanage fcontext -a -t public_content_t 'index.html'
# restorecon -v 'index.html'
***** 插件 catchall_boolean (32.5 置信度) 建议 ***********************************
如果你想 allow httpd to enable homedirs
Then 必须启用 'httpd_enable_homedirs' 布尔值告知 SELinux 此情况。
Do
setsebool -P httpd_enable_homedirs 1
***** 插件 catchall_boolean (32.5 置信度) 建议 ***********************************
如果你想 allow httpd to unified
Then 必须启用 'httpd_unified' 布尔值告知 SELinux 此情况。
Do
setsebool -P httpd_unified 1
***** 插件 catchall (4.5 置信度) 建议 ********************************************
如果你相信 httpd应该允许_BASE_PATH read 访问 index.html file默认情况下。
Then 应该将这个情况作为 bug 报告。
可以生成本地策略模块以允许此访问。
Do
暂时允许此访问权限执行:
# ausearch -c 'httpd' --raw | audit2allow -M my-httpd
# semodule -X 300 -i my-httpd.pp
更多信息:
源环境 (Context) system_u:system_r:httpd_t:s0
目标环境 unconfined_u:object_r:httpd_user_content_t:s0
目标对象 index.html [ file ]
源 httpd
源路径 /usr/sbin/httpd
端口 <Unknown>
主机 server
源 RPM 软件包 httpd-2.4.37-64.module+el8.10.0+1717+030a9fed.x86_
64
目标 RPM 软件包
SELinux 策略 RPM selinux-policy-targeted-3.14.3-139.el8_10.noarch
本地策略 RPM selinux-policy-targeted-3.14.3-139.el8_10.noarch
Selinux 已启用 True
策略类型 targeted
强制模式 Permissive
主机名 server
平台 Linux server 4.18.0-553.el8_10.x86_64 #1 SMP Fri
May 24 13:05:10 UTC 2024 x86_64 x86_64
警报计数 18
第一个 2025-06-19 22:20:30 CST
最后一个 2025-06-19 23:01:15 CST
本地 ID 8d373a05-410e-4622-bcf6-f8b6266e9bfa
原始核查信息
type=AVC msg=audit(1750345275.801:340): avc: denied { read } for pid=6385 comm="httpd" name="index.html" dev="dm-2" ino=157 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_user_content_t:s0 tclass=file permissive=1
type=AVC msg=audit(1750345275.801:340): avc: denied { open } for pid=6385 comm="httpd" path="/home/robinkool/public_html/index.html" dev="dm-2" ino=157 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_user_content_t:s0 tclass=file permissive=1
type=SYSCALL msg=audit(1750345275.801:340): arch=x86_64 syscall=openat success=yes exit=EFAULT a0=ffffff9c a1=7f0a1000a678 a2=80000 a3=0 items=0 ppid=6381 pid=6385 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm=httpd exe=/usr/sbin/httpd subj=system_u:system_r:httpd_t:s0 key=(null)
Hash: httpd,httpd_t,httpd_user_content_t,file,read
#直接粘贴给出的命令就可以解决问题