前言:


SELinux是一个很深奥的东西,我问过身边好多运维技术人员,他们公司服务器的SElinux在生产环境中是开启状态还是关闭状态,得到一个统一的答案——直接关闭,无一例外。

网上也有一句话——一个资深的运维工程师,他系统的SELinux一定是关闭的。

所以说,想了解SELinux的,可以了解一下,为了以防以后自己所在的公司要求必须开启SELinux,但自己又不懂,那就尴尬了,不了解也无所谓,因为遇到强制开启SELinux的公司,也不是那么容易的事情。

上面说了那么一大堆,那么什么是SELinux呢?这篇文章就要聊一聊SELinux的一些概念及设置方法。

正文:


SELinux它是安全强化的linux含义,我们都知道在Linux中,一个文件能不能被当前用户所读取到,是由该用户对这个文件所具有的权限来决定的,熟知的一般权限有读、写、执行,特殊的一点的权限又有lsattr命令查看到的特殊权限,又或者是SUID、SGID、SBIT等特殊权限,这些权限基本都是针对用户来进行控制的,而SELinux类似这些权限,但又不是和这些权限一个种类的,前面说到的权限是针对用户进行权限控制的,而SELinux是针对某个进程进行控制的,那么,当用户对一个文件进行读取操作时,系统是如何执行的呢?下面附上鸟哥的私房菜中的一张图片一起来看一下:
Linux系统上的SELinux究竟是个什么?

上图的重点在于程序如何取得目标的资源访问权限!由上图可以看出来,程序想要读取一个文件,必须要先通过SELinux政策内的规则,然后再进行安全性文本的对比,若对比失败则无法进行下一步验证(验证针对用户设置的权限),这里的政策、安全性文本都是由SELinux来提供的,总结来说,用户要读取一个文件,该读取进程必须要通过SELinux的检测(当然,SELinux要在开启状态下),然后才有资格针对用户去进行权限验证,若SELinux是关闭状态,毫无疑问咯,直接验证用户的权限即可决定是否可以读取到该文件。

结论:用户读取一个文件,必须该进程先通过SELinux验证,然后才是对用户的权限进行验证。

关于上面提到的政策及安全性文本,我也没搞的太明白,里面的东西过于深奥(这是我一个在国外工作的朋友对我说的,毕业两年,年薪30W+,我挺佩服的一个人)。

我们不搞那么深奥的东西(主要是我也没怎么搞懂),我们就来一些简单的。

1、如何查看SELinux对一个文件的权限控制?

[root@node1 ~]# ls -Z       #这就是查看SELinux相关权限的选项
-rw-------. root root 'system_u':'object_r':'admin_home_t':s0 anaconda-ks.cfg
#最后一列是文件名
-rw-r--r--  root root ?                                cpu.cfs_quota_us~
-rw-r--r--. root root system_u:object_r:admin_home_t:s0 initial-setup-ks.cfg
#在上面字体颜色有些特殊的便是SELinux的特殊权限

我刚看到这些东西的时候,内心的想法就是:我的天哪,这是什么鬼东西!哈哈!!!

不要慌,问题不大,我这篇文章存在的意义就是将复杂的问题简单化,你需要了解的是“ 'system_u':'object_r':'admin_home_t'”每个文件的三个字段的意思,但也不需要全部了解,你只需要知道每一段后面“_u、_r”的含义,以及最主要的一段“_t”这段是什么就行了,前面两段““_u、_r”选择性忽略就行了。

相关解释如下:
_u(user):相当于账号方面的身份识别!
_r(role):通过角色字段,我们可以知道这个资料是属于进程、文件资源还是代表使用者。一般的角色有:object_r:代表的是文件或目录等文件资源,这应该是最常见的;system_r:代表的就是进程啦!不过,一般使用者也会被指定成为 system_r。
_t(type):这个最重要,前面两个“user”和“role”基本不重要,重要的是在于这个类型(type)字段!基本上一个主体进程能不能读取到这个文件资源,就与这个字段有关。

上述是SELinux对文件的权限控制,SELinux也是针对于进程来进行权限控制的,那么,如何查看进程所对应的SELinux权限呢?请看下面:

[root@localhost ~]# ps -eZ             #执行该命令,查看进程所对应的SELinux权限
LABEL                              PID TTY          TIME CMD
system_u:system_r:init_t:s0          1 ?        00:00:01 systemd
system_u:system_r:kernel_t:s0        2 ?        00:00:00 kthreadd
system_u:system_r:kernel_t:s0        3 ?        00:00:00 ksoftirqd/0
system_u:system_r:kernel_t:s0        4 ?        00:00:00 kworker/0:0
system_u:system_r:kernel_t:s0        5 ?        00:00:00 kworker/0:0H
system_u:system_r:kernel_t:s0        6 ?        00:00:00 kworker/u256:0
system_u:system_r:kernel_t:s0        7 ?        00:00:00 migration/0
                   ...............#省略部分内容
#当然了,SELinux必须是开启状态下,才可查看这些信息,如果SELinux关闭,是查不到的。

前面一直在说开启、关闭SELinux,那么怎么操作呢?请继续看下去。

相关命令如下:

[root@localhost ~]# getenforce               #查看当前SELinux状态
Enforcing
[root@localhost ~]# setenforce 0            #将状态设置为宽容模式
[root@localhost ~]# getenforce                #再继续查看是否更改成功
Permissive
[root@localhost ~]# setenforce 1              #再次改为强制状态
[root@localhost ~]# getenforce                 #再次查看
Enforcing

SELinux共有三种模式:Enforcing、Permissive、disabled。关于这三种模式的解释如下:

  • Enforcing:强制模式,处于该状态模式下的SELinux是正常运行的,可以对程序的读取起到很好的控制作用;
  • Permissive:宽容模式,处于该状态下的SELinux也是正在运行的,只是对于程序的读取不进行限制,只是记录下日志等相关信息。
  • disabled:禁用模式,就是直接关闭了,如果想要改为此种模式,需要修改配置文件,并重新启动服务器。

使用命令的话,只可以将SELinux暂时性的改为强制模式或宽容模式,不能修改为禁用模式,并且是一次性修改的,如果重启的话,它将会读取到配置文件中的模式继续运行。

SELinux的配置文件介绍如下:

[root@node1 ~]# vim /etc/selinux/config 

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#以下是SELinux的三种工作模式介绍:enforcing、permissive、disabled
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing                        #这里是修改SELinux的运行模式
# SELINUXTYPE= can take one of three two values:
#以下是SELinux的三种政策介绍,targeted、minimum、mls
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected. 
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted           #这里是修改SELinux的三种政策
#一般是修改SELinux的工作模式即可,这里不谈它的三种政策

上面是默认的政策与启动的模式!你要注意的是,如果改变了政策则需要重新启动;如果由 enforcing或 permissive 改成 disabled ,或由 disabled 改成其他两个,那也必须要重新启动。这是因为 SELinux是整合到核心里面去的, 你只可以在 SELinux 运作下切换成为强制 (enforcing) 或宽容 (permissive)模式,不能够直接关闭 SELinux 的! 如果刚刚你发现getenforce 出现 disabled 时,请到上述文件修改成为 enforcing 然后重新启动吧!(重启的过程会很慢,并且很有可能重启不起来,我没有去找无法重启的解决办法,自行解决吧)。

来两个小小的实验吧!

服务器node1和客户端,node1上面有web服务和FTP服务。然后客户端访问( 注意,此时SELinux是开启状态):

[root@node1 ~]# yum -y install httpd           #安装web服务
[root@node1 ~]# yum -y install vsftpd*        #安装FTP服务
[root@node1 ~]# systemctl start httpd          #启动web服务
[root@node1 ~]# systemctl start vsftpd        #启动FTP服务
[root@node1 ~]# echo "test web `date +%F`" > /var/www/html/test.html   #做一个测试网页
[root@node1 ~]# ll -Z /var/www/html/test.html    #查看该网页的type
-rw-r--r--. root root unconfined_u:object_r:'httpd_sys_content_t':s0 /var/www/html/test.html
#可以看到是属于httpd进程的
[root@node1 ~]# echo -e "ftptest \n`date +%F`" > /var/ftp/pub/test.txt   #做一个文件放到ftp目录下
[root@node1 ~]# ll -R -Z /var/ftp/               #查看FTP根目录下文件的type类型
/var/ftp/:
drwxr-xr-x. root root system_u:object_r:public_content_t:s0 pub

/var/ftp/pub:
-rw-r--r--. root root unconfined_u:object_r:public_content_t:s0 test.txt
[root@node1 ~]# getenforce            #确认当前SELinux状态是开启状态
Enforcing
#为了避免防火墙的干扰,这里关闭firewalld防火墙(防火墙不是这个博文要说的)

客户端访问node1的web服务和FTP服务:

访问node1的web服务:
Linux系统上的SELinux究竟是个什么?

访问node1的FTP服务:
Linux系统上的SELinux究竟是个什么?

1、对web网页进行测试

现在改一下web服务的网页文件,看看client是否还能访问的到:

[root@node1 ~]# chcon -t admin_home_t /var/www/html/test.html    #更改类型为“admin_home_t”
[root@node1 ~]# ll -Z /var/www/html/test.html      #查看是否更改成功
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /var/www/html/test.html
#OK,没问题,类型字段已经更改成功了

client再次访问测试:

Linux系统上的SELinux究竟是个什么?

那么将类型改回来,有两种方法,一种是使用命令chcon手动再次修改,刚才怎么改的,现在就怎么改回来,命令如下:

[root@node1 ~]# chcon -t httpd_sys_content_t /var/www/html/test.html     #更改类型,使用户可以正常访问

上面chcon命令可以改回来,但是比较麻烦,不建议使用,这里说一下restorecon这个命令

restorecon 命令可以让文件恢复正确的 SELinux type(恢复默认类型)。

[root@node1 ~]# ll -Z /var/www/html/test.html    #确认类型还是自己随便改的那个
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /var/www/html/test.html
[root@node1 ~]# restorecon -R /var/www/html/  #使用该命令,这里并没有指定那个网页文件
#是因为我想说“-R”这个选项,就是递归修改的意思
[root@node1 ~]# ll -Z /var/www/html/test.html     #查看,是否成功
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/test.html
#OK了,没问题,变成了它最初的类型字段

client端应该又可以访问了吧?一起瞧瞧:

Linux系统上的SELinux究竟是个什么?

OK,没问题了。关于web网页文件的测试至此结束!!!

2、对FTP服务进行测试

1、修改FTP服务的根目录

[root@node1 ~]# mkdir /test        #创建一个测试目录
[root@node1 ~]# usermod -d /test ftp     #将/test目录修改为FTP服务的默认根目录
#因为默认根目录是它的宿主目录,所以直接改它的宿主目录,生产环境中,还是建议更改FTP服务的配置文件
[root@node1 ~]# echo -e "Are you ok ? \n `date +%F`" > /test/aaa.txt     #写入一个测试文件
[root@node1 ~]# ll -Z /test/aaa.txt             #查看该文件的默认类型
-rw-r--r--. root root unconfined_u:object_r:default_t:s0 /test/aaa.txt
#由于这个文件和FTP服务进程没有关系,所以它的类型和刚安装时,/var/ftp/pub/test.txt的类型一样
[root@node1 ~]# systemctl restart vsftpd        #重启FTP服务,以便更改生效

2、客户端访问测试:
Linux系统上的SELinux究竟是个什么?

当然了,此时,也可以使用chcon命令手动更改该文件的类型,改为和/var/ftp/pub/test.txt一样的类型,但是不可以使用restorecon命令,因为restorecon命令一般是将文件恢复为它初始的类型,而这个文件现在的类型就是初始类型啊!所以,需要另想其他方法。

方法一:使用setsebool命令修改它的布尔值:

[root@node1 ~]# getsebool -a | grep ftpd         #查看ftp相关的进程控制
ftpd_anon_write --> off     #off表示关闭
ftpd_connect_all_unreserved --> off
ftpd_connect_db --> off
ftpd_full_access --> off
ftpd_use_cifs --> off
ftpd_use_fusefs --> off
ftpd_use_nfs --> off
ftpd_use_passive_mode --> off
[root@node1 ~]# setsebool -P ftpd_full_access 1   
#使用setsebool命令修改它访问相关的布尔值,1表示on(开启),0表示off(关闭)。
[root@node1 ~]# getsebool -a | grep ftpd         #再次查看
ftpd_anon_write --> off
ftpd_connect_all_unreserved --> off
ftpd_connect_db --> off
ftpd_full_access --> on       #刚才就是将这个访问相关的进程开启了
ftpd_use_cifs --> off
ftpd_use_fusefs --> off
ftpd_use_nfs --> off
ftpd_use_passive_mode --> off
[root@node1 ~]# getenforce           #确认SELinux现在是开启的
Enforcing

client再次访问:
Linux系统上的SELinux究竟是个什么?

OK,没问题,访问到了

方法2:使用setroubleshoot 工具
Redhat公司针对SELinux发布了一个非常好的工具——setroubleshoot (可以将SELinux的错误讯息写入 /var/log/messages中,并且给出解决方案)
(1)确认setroubleshoot工具已安装

[root@node1 ~]# rpm -qa | grep setroubleshoot    #查询该命令是否安装
[root@node1 ~]# yum -y install setroubleshoot    #没有安装的话,使用该命令安装
[root@node1 ~]# tailf /var/log/messages         #动态刷新查看着日志消息

客户端访问:

Linux系统上的SELinux究竟是个什么?

(2)客户端访问失败的同时,服务器监控的日志消息将会显示如下提示:
Linux系统上的SELinux究竟是个什么?

(3)我们运行一下它提示的命令:

[root@node1 ~]# sealert -l 1e24155c-7602-4c51-8eb6-93ec8f77600f     #执行日志中提示的信息
SELinux is preventing vsftpd from read access on the directory test.
#下面的(57.6 confidence)的含义是这一段提供的信息解决这个问题的几率有多大
#一般几率越大的越靠前,所以一般看第一个就行
*****  Plugin catchall_boolean (57.6 confidence) suggests   ******************

If 要 allow ftpd to full access
Then 必须启用 'ftpd_full_access' 布尔值告知 SELinux 此情况。
可以阅读 'None' 手册页面来了解详情。
Do       #Do表示要运行以下命令来解决问题
setsebool -P ftpd_full_access 1          #就是这条命令咯,我去......好像和我们第一种方法一样....

*****  Plugin catchall_labels (36.2 confidence) suggests   *******************
#这一段表示解决问题的几率只有36.2%,越往下几率越小
If you want to allow vsftpd to have read access on the test directory
Then 必须更改 test 中的标签
Do
# semanage fcontext -a -t FILE_TYPE 'test'
其中 FILE_TYPE 为以下内容之一:admin_home_t, bin_t, boot_t, cache_home_t, cert_t, config_home_t, data_home_t, dbusd_etc_t, device_t, devpts_t, etc_runtime_t, etc_t, faillog_t, file_context_t, fonts_cache_t, fonts_t, ftpd_tmp_t, ftpd_tmpfs_t, ftpd_var_run_t, gconf_home_t, gnome_home_t, httpd_user_content_t, httpd_user_script_exec_t, krb5_conf_t, krb5_host_rcache_t, lib_t, locale_t, man_cache_t, man_t, mozilla_plugin_rw_t, net_conf_t, nscd_var_run_t, proc_t, public_content_rw_t, public_content_t, root_t, samba_etc_t, security_t, shell_exec_t, slapd_cert_t, src_t, sssd_public_t, sysfs_t, system_conf_t, system_db_t, systemd_logind_sessions_t, telepathy_cache_home_t, telepathy_data_home_t, textrel_shlib_t, tmp_t, tmpfs_t, udev_var_run_t, user_fonts_t, user_home_dir_t, user_home_t, user_tmp_t, usr_t, var_auth_t, var_lib_t, var_lock_t, var_log_t, var_run_t, virt_home_t, xferlog_t。
然后执行:
restorecon -v 'test'            #这个几率只有36.2%的提示信息,让我们运行这条命令
#那知道为什么几率这么小么?因为这条命令是让我们将test恢复默认类型,肯定不会成功呀,它的默认类型就没有改过

                #.....................省略部分内容
#其实这些提示信息,就是/var/log/messages日志中记录的,只不过这样显示的看起来直观了很多
[root@node1 ~]# setsebool -P ftpd_full_access 1        #那就执行以下这个57.6%几率的命令咯

毫无疑问,可以正常访问到它的ftp服务:

Linux系统上的SELinux究竟是个什么?

———————— 本文至此结束,感谢阅读 ————————