RHCE9学习指南 第25章 seLinux介绍

在Windows系统中安装了一些安全软件后,当执行某个命令时,如果安全软件认为这个命令对系统是一种危害,则会阻止这个命令继续运行。例如,在powershell中创建一个用户 net user tom /add,安全软件会认为这个操作是不安全的,然后会阻止,如图25-1所示。
file
图25-1 Windows上安全软件保护系统

同理,在rhel/centos中的selinux实现的是类似的功能,selinux全称是Security-Enhanced Linux,目的是提高系统的安全性。当我们执行某个操作时如果selinux认为此操作有危险,则会拒绝进一步的访问。

25.1 了解上下文

在开启了selinux的情况下,selinux会为每个文件、每个进程都分配一个标签,这个标签我们称之为上下文(context),后续说标签和上下文是同一个概念,查看上下文时需要加上Z选项。例如,查看进程的上下文,命令如下。

[root@server ~]# ps axZ | grep -v grep | grep httpd
system_u:system_r:httpd_t:s0   ...   /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0   ...  /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0   ...  /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0   ...   /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0   ...   /usr/sbin/httpd -DFOREGROUND
[root@server ~]#

这里可以看到,httpd进程的上下文为httpd_t。
查看文件的上下文,命令如下。

[root@server ~]# ls -dZ /var/www/html/
system_u:object_r:httpd_sys_content_t:s0 /var/www/html/
[root@server ~]#

这里可以到/var/www/html/的上下文为httpd_sys_content_t。

特定上下文的进程,只能访问特点上下文的文件,上下文为httpd_t的进程可以访问上下文为httpd_sys_content_t的文件或目录的,如图25-2所示。
file
图25-2 了解上下文
假设一个进程xx的标签是aa-p,它能访问标签为aa-f的文件,所以xx进程访问文件aa是没问题的,因为标签匹配了。但是进程xx访问文件bb时却是访问不了的,即使bb文件的权限为777也是访问不了的,因为文件bb的标签是bb-f。

下面做一个测试,在server上创建目录/web,并写一些测试数据到/web/index.html中,命令如下。

[root@server ~]# mkdir /web
[root@server ~]# echo 5555 > /web/index.html
[root@server ~]#

查看/web/的上下文,命令如下。

[root@server ~]# ls -dZ /web/
unconfined_u:object_r:default_t:s0 /web/
[root@server ~]#

可以看到,上下文为default_t。
把/web软连接到/var/www/html/www,命令如下。

[root@server ~]# ln -s /web /var/www/html/www
[root@server ~]#

查看/var/www/html/下的内容,命令如下。

[root@server ~]# ls /var/www/html
index.html  www
[root@server ~]#

这里的www是/web的软连接(快捷方式),当我们在地址栏中输入“192.168.26.100/www”时,其实访问的是/web/中的index.html。
确保httpd服务是运行的,命令如下。

[root@server ~]# systemctl restart httpd
[root@server ~]# systemctl is-active httpd
active
[root@server ~]#

确保防火墙放行了http服务,命令如下。

[root@server ~]# firewall-cmd --add-service=http
success
[root@server ~]#

现在客户端上访问此内容,结果如图25-3所示。
file
图25-3 在宿主机上访问不到

发现是访问是被拒绝的,原因是因为当客户端在浏览器地址栏输入“192.168.26.101/www”连接到服务器时,服务器会有一个httpd进程来“接待”这个客户端的连接请求,然后httpd根据用户的请求去访问目录/web/,如图25-4所示。
file
图25-4 了解上下文

前面已经看到httpd进程的上下文是httpd_t,/web的上下文是default_t,这两个是不匹配的,所以进程httpd访问目录/web/时被拒绝。

但是httpd进程是可以正常访问/var/www/html的(上下文为httpd_sys_content_t),考虑如果把/web/的上下文改成httpd_sys_content_t是不是就可以使得进程httpd能访问了呢?
改变上下文的命令如下所示。

chcon -R -t 上下文 目录

这里选项R的意思是递归。
把/web/上下文改成httpd_sys_content_t,命令如下。

[root@server ~]# chcon -R -t httpd_sys_content_t /web/
[root@server ~]# 

再次查看/web的上下文信息,命令如下。

[root@server ~]# ls -dZ /web/
unconfined_u:object_r:httpd_sys_content_t:s0 /web/
[root@server ~]#

现在已经是httpd_sys_content_t了,在浏览器测试结果如图25-5所示。
file
图25-5 宿主机现在能访问了
发现是可以正常访问的了。如果要恢复目录的默认上下文可以用“restorecon -R 目录”,下面恢复/web的上下文,命令如下。

[root@server ~]# restorecon -R /web/
[root@server ~]#

再次查看/web的上下文信息,命令如下。

[root@server ~]# ls -dZ /web/
unconfined_u:object_r:default_t:s0 /web/
[root@server ~]#

可以看到,/web的上下文又恢复成了default_t了,此时刷新浏览器之后又是被拒绝。
如果想修改默认上下文,可以用如下命令。

semanage fcontext -a -t httpd_sys_content_t "/目录(/.*)?"

这里(/.*)? 表示"/目录"本身及里面所有的东西。
如果要是想删除默认上下文,把上面命令的-a换成-d即可,命令如下。

semanage fcontext -d -t httpd_sys_content_t "/目录(/.*)?"

下面修改/web默认上下文,命令如下。

[root@server ~]# semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"
[root@server ~]#

下面查看/web的上下文,命令如下。

[root@server ~]# ls -dZ /web
unconfined_u:object_r:default_t:s0 /web
[root@server ~]#

可以看到,当前仍然是default_t,说明semanage修改的只是默认值,并没有改变当前的上下文,要改变当前上下文,仍然需要使用restorecon命令,命令如下。

[root@server ~]# restorecon -R /web
[root@server ~]# ls -dZ /web
unconfined_u:object_r:httpd_sys_content_t:s0 /web
[root@server ~]#

可以看到,此时已经修改了默认的上下文。

25.2 端口上下文

端口也是有上下文的,如果一个端口,没有上下文或上下文和进程不匹配,则进程也是没法去访问此端口。
查看系统所有端口上下文的命令是semanage port -l(小写字母l,list的意思)

练习:

请通过如下命令吧httpd端口改为808,命令如下。

[root@server ~]# sed -i '/^Listen/cListen 808' /etc/httpd/conf/httpd.conf 
[root@server ~]#

然后重启httpd,命令如下。

[root@server ~]# systemctl restart httpd
Job for httpd.service failed because the control process exited with error code.
See "systemctl status httpd.service" and "journalctl -xe" for details.
[root@server ~]# 

发现启动服务失败,通过journalctl -xe | grep httpd查看日志,发现里面有一段话,如下所示。

[root@server ~]# journalctl -xe  | grep httpd
    ...输出...
12月16 22:04:52 server.rhce.cc setroubleshoot[613352]: SELinux is preventing /usr/sbin/httpd from name_bind access on the tcp_socket port 808. For complete SELinux messages run: sealert -l e0bd7550-75af-4206-90cb-e0f055de4db1
    ...输出...
root@server ~]# 

意思是没法绑定808端口,这是因为808没有对应的上下文,命令如下。

[root@server ~]# semanage port -l | grep '\b808\b'
[root@server ~]#

这样httpd进程是访问不了8088端口的。但是端口80是正常工作的,查看下80的上下文,命令如下。

[root@server ~]# semanage port -l | grep '\b80\b'
http_port_t           tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
[root@server ~]#

这里看到端口80的上下文是http_port_t。如果我把端口808的上下文改成和端口80一样不就可以了吗?试试修改808的上下文。
修改端口上下文的语法如下。

semanage port  -a  -t 上下文 -p 协议 端口

如果要删除端口上下文语法如下。

semanage port  -d  -t 上下文 -p 协议 端口

下面把端口808的上下文改为http_port_t,命令如下。

[root@server ~]# semanage port -a -t http_port_t -p tcp 808
[root@server ~]#

这句话的意思是把端口808的上下文改成http_port_t。
再次查看下808的上下文,命令如下。

[root@server ~]# semanage port -l | grep '\b808\b'
http_port_t         tcp      808, 80, 81, 443, 488, 8008, 8009, 8443, 9000
[root@server ~]#

现在再次重启httpd服务,命令如下。

[root@server ~]# systemctl restart httpd
[root@server ~]#

可以正常启动,查看下端口监听情况,命令如下。

[root@server ~]# netstat -ntulp | grep :808
tcp6       0      0 :::808      ...输出...    LISTEN      613725/httpd        
[root@server ~]#

端口808也正常运行了。

25.3 了解布尔值

布尔值可以理解是一个功能开关,如图25-6所示。
file
图25-6 了解布尔值
在没有selinux的情况下,电灯亮不亮完全由开关控制,打开开关电灯亮,关闭开关电灯灭。现在有了selinux之后,情况如图25-7所示。
file
图25-7 布尔值
现在电灯亮还是不亮,不能完全由原来的开关A决定,这当中selinux也具有决定权。如果你把开关A打开,但是selinux不允许打开,则电灯仍然是不亮的。

要查看系统中所有的selinux布尔值可以通过:getsebool -a 查看。

下面看一个例子,在前面讲到yum时,已经在server上启动了vsftpd并开启了匿名用户访问,匿名用户是ftp或anonymous。

下面开始测试匿名用户是否能往ftp中写入内容。
(1)在server上创建/var/ftp/incoming目录,并把所有者和所属组改为ftp,命令如下。

[root@server ~]# mkdir /var/ftp/incoming
[root@server ~]# chown ftp.ftp /var/ftp/incoming
[root@server ~]# 

改所有者和所属组的目的是为让匿名用户(ftp用户)有足够的权限去写。
(2)修改配置文件/etc/vsftpd/vsftpd.conf,添加如下两行。

anon_upload_enable=YES
anon_mkdir_write_enable=YES

这两行的作用是设置允许匿名用户可以往ftp中写东西。这两行加在哪里都可以,原本配置文件中就有了这两行,只是被注释掉了,所以直接找到这两行内容把最前面的#去掉也可以。
然后重启vsftpd,命令如下。

[root@server ~]# systemctl restart vsftpd
[root@server ~]#

在server2上自行安装lftp,使用lftp登录并进入incoming目录中(如果不指定用户名则是匿名用户登录)。

[root@server2 ~]# lftp 192.168.26.101/incoming
cd 成功, 当前目录=/incoming
lftp 192.168.26.101:/incoming> ls
lftp 192.168.26.101:/incoming>

可以看到,使用匿名用户是可以登录成功的(注,如果想使用指定用户登录则需要用-u选项),并且incoming目录下没有任何文件。
(3)到server2上测试把/etc/hosts文件上传进去,命令如下。

lftp 192.168.26.101:/incoming> put /etc/hosts
193 bytes transferred
lftp 192.168.26.101:/incoming> ls
-rw-------    1 14       50       193 Nov 16 15:13 hosts
lftp 192.168.26.101:/incoming> 

这里是已经上传上去了。
切换到server上,开启相关布尔值。
先查看布尔值 ftpd_full_access是否开启了,命令如下。

[root@server ~]# getsebool -a | grep ftpd_full_access
ftpd_full_access --> on
[root@server ~]#

这里显示为on,说明已经开启了。这个是我们在讲搭建yum源时开启的。
开启布尔值的语法如下。

setsebool 布尔值 on  或者
setsebool 布尔值 1 

关闭布尔值的语法是

setsebool 布尔值 off  或者
setsebool 布尔值 0

setsebool可以加上-P(大写)选项,表示永久生效,即重启系统之后也生效。
因为这里已经开启了布尔值ftpd_full_access,所以下面先关闭这个布尔值,命令如下。

[root@server ~]# setsebool -P ftpd_full_access off
[root@server ~]# 

再次切换到server2上上传一个文件,命令如下。

lftp 192.168.26.101:/incoming> put /etc/issue
put: /etc/issue: 访问失败: 553 Could not create file. (issue)
lftp 192.168.26.101:/incoming> quit
[root@server2 ~]#

这里发现上传失败。
再次切换到server上,执行如下命令。

[root@server ~]# setsebool -P ftpd_full_access off
[root@server ~]# 

25.4 了解selinux的模式

selinux一共有以下两种模式。

(1)Enforcing:如果不满足selinux条件,则selinux会阻止访问服务并提供警报。
(2)Permissive:如果不满足selinux条件,则selinux不阻止访问,但是会警报。

查看当前处于什么模式用getenforce命令,命令如下。

[root@server ~]# getenforce 
Enforcing
[root@server ~]#

要是想切换模式,需要用setenforce命令。

setenforce 1:切换到Enforcing模式。
setenforce 0:切换到Permissive模式。

下面开始查看及模式切换。

root@server ~]# setenforce 0
[root@server ~]# getenforce 
Permissive
[root@server ~]# setenforce 1
[root@server ~]# getenforce 
Enforcing
[root@server ~]# 

但是使用getenforce切换也只是临时生效,当重启系统之后又变成了默认的模式了。如果想修改默认的模式,可以通过修改配置文件/etc/selinux/config或/etc/sysconfig/selinux,后者是前者的快捷方式(软连接)。
使用vim打开/etc/selinux/config,如图25-8所示。
file
图25-8 修改selinux默认模式
其中SELINUX=后面的部分就是默认模式。如果想彻底关闭selinux,可以在此配置文件中内容改为SELINUX=disabled且重启才能生效。

要关闭selinux也可以执行如下命令
grubby --update-kernel ALL --args selinux=0
它会在/etc/default/grub这个文件里GRUB_CMDLINE_LINUX那行最后加上selinux=0参数,如下。

GRUB_CMDLINE_LINUX="crashkernel=...输出... rhgb quiet selinux=0"

然后重启系统,此时即使/etc/selinux/config里"SELINUX"的值设置为enforcing,等待重启系统之后执行getenforce命令也会看到selinux是Disabled的。

作业

1.确保selinux的状态是Enforcing模式,且永久生效

2.安装软件包httpd,设置让httpd除使用80外,也能开启端口83

3.创建目录/www, 在此目录中创建一个文件index.html, 内容为xxx

4.把/www这个目录软链接到/var/www/html/www2。

5.请做合适的设置,之后在客户端浏览器上输入“192.168.26.X:83/www2/index.html”,按【Enter】键能看到xxx。
其中192.168.26.X换成你自己的IP

相关新闻

发表回复

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

                                                                                                                                    RHCE9学习指南连载,点击阅读