Linux系统上的SELinux究竟是个什么?
前言:
SELinux是一个很深奥的东西,我问过身边好多运维技术人员,他们公司服务器的SElinux在生产环境中是开启状态还是关闭状态,得到一个统一的答案--直接关闭,无一例外。
网上也有一句话--一个资深的运维工程师,他系统的SELinux一定是关闭的。
所以说,想了解SELinux的,可以了解一下,为了以防以后自己所在的公司要求必须开启SELinux,但自己又不懂,那就尴尬了,不了解也无所谓,因为遇到强制开启SELinux的公司,也不是那么容易的事情。
上面说了那么一大堆,那么什么是SELinux呢?这篇文章就要聊一聊SELinux的一些概念及设置方法。
正文:
SELinux它是安全强化的linux含义,我们都知道在Linux中,一个文件能不能被当前用户所读取到,是由该用户对这个文件所具有的权限来决定的,熟知的一般权限有读、写、执行,特殊的一点的权限又有lsattr命令查看到的特殊权限,又或者是SUID、SGID、SBIT等特殊权限,这些权限基本都是针对用户来进行控制的,而SELinux类似这些权限,但又不是和这些权限一个种类的,前面说到的权限是针对用户进行权限控制的,而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 CMDsystem_u:system_r:init_t:s0 1 ? 00:00:01 systemdsystem_u:system_r:kernel_t:s0 2 ? 00:00:00 kthreaddsystem_u:system_r:kernel_t:s0 3 ? 00:00:00 ksoftirqd/0system_u:system_r:kernel_t:s0 4 ? 00:00:00 kworker/0:0system_u:system_r:kernel_t:s0 5 ? 00:00:00 kworker/0:0Hsystem_u:system_r:kernel_t:s0 6 ? 00:00:00 kworker/u256:0system_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服务:
访问node1的FTP服务:
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再次访问测试:
那么将类型改回来,有两种方法,一种是使用命令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端应该又可以访问了吧?一起瞧瞧:
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、客户端访问测试:
当然了,此时,也可以使用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 --> offftpd_connect_db --> offftpd_full_access --> offftpd_use_cifs --> offftpd_use_fusefs --> offftpd_use_nfs --> offftpd_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 --> offftpd_connect_all_unreserved --> offftpd_connect_db --> offftpd_full_access --> on #刚才就是将这个访问相关的进程开启了ftpd_use_cifs --> offftpd_use_fusefs --> offftpd_use_nfs --> offftpd_use_passive_mode --> off[root@node1 ~]# getenforce #确认SELinux现在是开启的Enforcing
client再次访问:
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 #动态刷新查看着日志消息
客户端访问:
(2)客户端访问失败的同时,服务器监控的日志消息将会显示如下提示:
(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 accessThen 必须启用 '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 directoryThen 必须更改 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服务:
-------- 本文至此结束,感谢阅读 --------