本章主要介绍在RHEL8中如何使用 SELinux。
- 了解什么是 SELinux
- 了解 SELinux 的上下文
- 配置端口上下文
- 了解SELinux的布尔值
- 了解SELinux的模式
在 Windows系统中安装了一些安全软件后,当执行某个命令时,如果安全软件认为这个
命令对系统是一种危害,则会阻止这个命令继续运行。例如,在powershell中创建一个用户
net user tom /add,安全软件会认为这个操作是不安全的,然后会阻止,如图26-1所示。
RHEL/CentOS 中的SELinux实现的是类似的功能,SELinux全称是Security-Enhanced
Linux,目的是提高系统的安全性。当我们执行某个操作时,如果SELinux认为此操作有危
险,则会拒绝进一步的访问。
26.1 了解上下文
在开启了SELinux 的情况下,SELinux 会为每个文件、每个进程都分配一个标签,这个标
签我们称为上下文(context),后续说的标签和上下文是同一个概念,查看上下文时需要
加上Z选项。例如,查看进程的上下文,命令如下。
[root@pp ~]# ps axZ | grep -v grep | grep httpd
system_u:system_r:httpd_t:s0 36960 ? Ss 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 36961 ? S 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 36962 ? Sl 0:01 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 36963 ? Sl 0:01 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 36964 ? Sl 0:01 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 37245 ? Sl 0:01 /usr/sbin/httpd -DFOREGROUND
[root@pp ~]#
可以看到,httpd进程的上下文为httpd_t。
查看文件的上下文,命令如下。
[root@pp ~]# ls -dZ /var/www/html/
system_u:object_r:httpd_sys_content_t:s0 /var/www/html/
[root@pp ~]#
可以看到,/var/www/html的上下文为httpd_sys_content_t。
特定上下文的进程,只能访问特定上下文的文件,上下文为httpd_t的进程可以访问上下
文为httpd_sys _content_t的文件或目录。
如图26-2所示,假设一个xx进程的标签是aa-p,它能访问
标签为aa-f的文件,所以xx进程访问文件aa是没问题的,因
为标签匹配了。但是xx进程访问文件bb时却是访问不了
的,即使文件bb的权限为777也是访问不了的,因为文件
bb的标签是bb-f。
下面做一个测试。
在server上创建目录/web,并写一些测试数据到/web/index.html中,命令如下。
[root@pp ~]# mkdir /web
[root@pp ~]# echo 555 > /web/index.html
[root@pp ~]#
查看/web 的上下文,命令如下。
[root@pp ~]# ls -dZ /web/
unconfined_u:object_r:default_t:s0 /web/
[root@pp ~]#
可以看到,/web 的上下文为 default_t。
把/web软链接到/var/www/html/www,命令如下。
[root@pp ~]# ln -s /web /var/www/html/www
[root@pp ~]#
这里的www是/web的软链接(快捷方式),当我们在地址栏中输
入“192.168.26.100/www"时,其实访问的是/web中的index.html。
确保httpd服务是运行的
确保防火墙放行了httpd服务,命令如下。
[root@pp ~]# firewall-cmd --add-service=http
success
[root@pp ~]#
在客户端上访问此内容,结果如图26-3所示。
发现访问是被拒绝的,原因是当客户端在浏览器的地址栏中输
入“192.168.26.101/www"连接到服务器时,服务器会有一个httpd进程来“接待”这个客
户端的连接请求,然后 httpd根
据用户的请求去访问目录/web,如图26-4所示。
前面已经看到httpd进程的上下文是httpd_t,/web的上下文是default_t,这两个是不匹配
的,所以 httpd进程访问目录/web时被拒绝。
但是httpd进程是可以正常访问/var/www/html的(上下文为httpd_sys_content_t),考
虑如果把/web的上下文改成 httpd sys content t是不是就可以使httpd进程能访问了呢?
改变上下文的命令如下。
1 chcon ‐R ‐t 上下文 目录
这里-R选项的意思是递归。
把/web的上下文改成httpd_sys_content_t,命令如下。
[root@pp ~]# chcon -R -t httpd_sys_content_t /web/
[root@pp ~]#
再次查看/web的上下文,命令如下。
[root@pp ~]# ls -dZ /web/
unconfined_u:object_r:httpd_sys_content_t:s0 /web/
[root@pp ~]#
现在已经是 httpd_sys_content_t了,浏览器测
试结果,可以正常访问量
如果要恢复目录的默认
上下文,可以用“restorecon -R 目录”命令。下
面恢复/web的上下文,命令如下。
[root@pp ~]# restorecon -R /web/
[root@pp ~]#
再次查看/web的上下文,命令如下。
[root@pp ~]# ls -dZ /web/
unconfined_u:object_r:default_t:s0 /web/
[root@pp ~]#
可以看到,/web的上下文又恢复成default t了,此时刷新浏览器之后又是被拒绝。
如果想修改默认上下文,可以用如下命令。
这里(/.*)?表示“/目录”本身及里面所有的内容。
如果想删除默认上下文,把上面命令的-a换成-d即可,命令如下。
1 semanage fcontext ‐d ‐t httpd_sys_content_t "/目录(/.*)?"
下面修改/web 的默认上下文,命令如下。
[root@pp ~]# semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"
[root@pp ~]#
查看/web 的上下文,命令如下。
[root@pp ~]# ls -dZ /web/
unconfined_u:object_r:default_t:s0 /web/
[root@pp ~]#
可以看到,当前仍然是 default_t,说明semanage修改的只是默认值,并没有改变当前
上下文,要改变当前上下文,仍然需要使用restorecon命令,命令如下。
[root@pp ~]# restorecon -R /web
[root@pp ~]# ls -dZ /web/
unconfined_u:object_r:httpd_sys_content_t:s0 /web/
[root@pp ~]#
可以看到,此时已经修改了默认上下文。
26.2 端口上下文
端口也是有上下文的,如果一个端口没有上下文或上下文和进程不匹配,则进程就无法访
问此端口。
查看系统所有端口上下文的命令是semanage port -l(小写字母l,list的意思)。
练习:请通过如下命令把httpd端口改为808,命令如下。
[root@pp ~]# sed ‐i '/^Listen/cListen 808' /etc/httpd/conf/httpd.c
onf
[root@server ~]#
然后重启 httpd服务,命令如下。
[root@pp ~]# systemctl restart httpd
Job for httpd.service failed because the control process exited with e
rror code.
See "systemctl status httpd.service" and "journalctl ‐xe" for details.
[root@pp ~]#
发现启动服务失败,通过journalctl -xe l grep httpd查看日志,发现里面有一段话,如
下所示。
[root@server ~]# journalctl -xe | grep httpd
4月 12 17:23:05 server.rhce.cc setroubleshoot[41672]: SELinux is preventing
/usr/sbin/httpd from name_bind access on the tcp_socket port 808. For complete
SELinux messages run: sealert -l b2ede99e-5451-46b9-99c8-3ff84f150288
这里的意思是无法绑定端口808,这是因为端口808没有对应的上下文,命令如下。
1 [root@pp ~]# semanage port ‐l | grep 'b808\b'
2 [root@pp ~]#
这样httpd进程是访问不了端口808的。但是端口80是正常工作的,查看端口80的上下文,
命令如下。
[root@pp ~]# semanage port ‐l | grep '\b80\b'
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
[root@pp ~]#
可以看到,端口80的上下文是 http_port_t。如果把端口808的上下文改成和端口80一样
不就可以了吗?试试修改端口808的上下文。
修改端口上下文的语法如下。
1 semanage port ‐a ‐t 上下文 ‐p 协议 端口
如果要删除端口上下文,语法如下。
1 semanage port ‐d ‐t 上下文 ‐p 协议 端口
下面把端口808的上下文改成http_port_t,命令如下。
[root@pp ~]# semanage port ‐a ‐t http_port_t ‐p tcp 808
这里的意思是把端口808的上下文改成http_port_t。
再次查看端口808的上下文,命令如下。
[root@pp ~]# semanage port ‐l | grep '\b808\b'
http_port_t tcp 808, 80, 81, 443, 488, 8008, 8009, 8443, 9000
[root@pp ~]#
再次重启httpd服务,命令如下。
1 [root@pp ~]# systemctl restart httpd
2 [root@pp ~]#
26.3 了解SELinux的布尔值
布尔值可以理解为一个功能开关,如图26-6所示。
在没有SELinux的情况下,电灯亮不亮完全由开关控制,打开开关电灯亮,关闭开关电灯
灭。现在有了SELinux,情况如图26-7所示。
现在电灯亮还是不亮,不能完全由原来的开关A决定,这当中 SELinux也具有决定权。如
果把开关A打开,但是 SELinux不允许打开,则电灯仍然是不亮的。
要查看系统中所有SELinux的布尔值可以使用getsebool -a命令。
下面看一个例子,在前面讲到yum时,已经在server上启动了vsftpd并开启了匿名用户访
问,匿名用户是ftp或anonymous。
下面开始测试匿名用户是否可以往ftp中写入内容。
(1)在server上创建/var/ftp/incoming目录,并把所有者和所属组改为ftp,命令如下。
[root@pp ~]# mkdir /var/ftp/incoming
[root@pp ~]# chown ftp.ftp /var/ftp/incoming/
[root@pp ~]#
(2)修改配置文件/etc/vsftpd/vsftpd.conf,添加如下两行。
anon_upload_enable=YES
anon_mkdir_write_enable=YES
这两行的作用是设置允许匿名用户往ftp中写内容。这两行加在哪里都可以,原本配置文
件中就有这两行,只是被注释掉了,所以直接找到这两行内容,把最前面的#去掉也可以。
然后重启vsftpd,命令如下。
[root@pp ~]# systemctl restart vsftpd
[root@pp ~]#
在server2上自行安装lftp,使用lftp登录并进入incoming目录中(如果不指定用户名,则
是匿名用户登录)。
[root@pp ~]# lftp 192.168.8.11/incoming
cd 成功, 当前目录=/incoming
lftp 192.168.8.11:/incoming> ls
lftp 192.168.8.11:/incoming>
可以看到,使用匿名用户是可以登录成功的(注意,如果想使用指定用户登录,则需要加
上u选项),并且 incoming目录下没有任何文件。
26.4 了解SELinux的模式
SELinux一共有以下两种模式。
(1) Enforcing:如果不满足SELinux条件,则SELinux 会阻止访问服务并提供警报。
(2) Permissive:如果不满足SELinux条件,则SELinux不会阻止访问,但是会警报。查看
当前处于什么模式用getenforce命令,命令如下。
[root@pp ~]# getenforce
Permissive
[root@pp ~]#
要是想切换模式,需要用setenforce命令。
setenforce 1:切换到Enforcing模式。
setenforce0:切换到Permissive模式。
[root@pp ~]# setenforce 0
[root@pp ~]# getenforce
Permissive
[root@pp ~]# setenforce 1
[root@pp ~]# getenforce
Enforcing
[root@pp ~]#
但是使用setenforce命令切换也只是临时生效,重启系统之后又变成默认模式了。如果想
修改默认模式,可以通过修改配置文件/etc/SELinux/config或/etc/sysconfig/SELinux,后
者是前者的快捷方式(软链接)。
使用vim打开/etc/SELinux/config,如图26-8所示。
其中 SELINUX=后面的部分就是默认模式(记住不是 SELINUXTYPE那行)。如果想彻底
关闭SELinux,只能在此配置文件中把内容改为SELINUX=disabled,且重启才能生效