SELinux是Security-Enhanced Linux的缩写,意思是安全强化的linux。
SELinux 主要由美国国家安全局(NSA)开发
传统的文件权限与账号的关系:自主访问控制,DAC(Discretionary Access Control)
当某个进程想要对文件进行访问时,系统就会根据该进程的所有者/用户组,并比较文件的权限,若通过权限检查,就可以访问该文件了。各种权限设置对root用户是无效的。
以策略规则制定特定程序读取特定文件:强制访问控制,MAC(Mandatory Access Control)
MAC可以针对特定的进程与特定的文件资源来进行权限的控制。也就是说,即使你是root,在使用不同的进程时,你所能取得的权限并不一定是root,而得要看当时该进程的设置而定。如此一来,就可以针对进程而不是用户对文件来进行访问控制。此外,这个进程也不能任意使用系统文件资源,因为每个文件资源也有针对进程设置可取用的权限。由于,整个系统进程那么多,文件那么多,所以SELinux也提供一些默认的策略(policy),并在该策略内提供多个规则,让你可以选择是否启用该控制规则。
SELinux是通过MAC的方式来控制管理进程,它控制的主体是进程,而目标则是该进程能否读取的文件资源。
1> 主体(subject):就是进程
2> 目标(object):被主体访问的资源,可以是文件、目录、端口等。
3> 策略(policy):由于进程与文件数量庞大,因此SELinux会依据某些服务来制定基本的访问安全策略。这些策略内还会有详细的规则(rule)来指定不同的服务开放某些资源的访问与否。
目前主要的策略有:
4> 安全上下文(security context):主体能不能访问目标除了策略指定外,主体与目标的安全上下文必须一致才能够顺利访问。但最终文件的成功访问还是与文件系统的rwx权限设置有关。
安全上下文用冒号分为四个字段:
Identify:role:type:mls
身份标识(Identify):相当于账号方面的身份标识,主要有以下三种常见的类型:
root:表示root的账号身份;
system_u:表示程序方面的标识,通常就是进程;
unconfined_u:代表的是一般用户账号相关的身份。
角色(role):通过角色字段,可知道这个数据是属于程序、文件资源还是代表用户。一般角色有:
object_r:代表的是文件或目录等文件资源;
system_r:代表的是进程。
类型(type):在默认的targeted策略中,Identify与role字段基本上是不重要的,重要的在于这个类型字段。而类型字段在文件与进程的定义不太相同,分别是:
type:在文件资源上面称为类型。
domain:在主体程序中则称为域。
domain需要与type搭配,则该程序才能够顺利读取文件资源。
灵敏度:最后一个字段是和MLS和MCS相关的东西,代表灵敏度,一般用s0、s1、s2来命名,数字代表灵敏度的分级。数值越大、灵敏度越高。
例如:
[root@server ~]# ls -Zd /usr/sbin/httpd /var/www/html/
-rwxr-xr-x. root root system_u:object_r:httpd_exec_t:s0 /usr/sbin/httpd
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html/
访问过程:
(1)首先,触发具有httpd_exec_t这个类型的/usr/sbin/httpd这个可执行文件;
(2)该文件的类型会让这个文件所造成的主体进程具有httpd这个域,我们的策略已经针对这个域制定了许多规则,其中包括这个域可以读取的目标资源类型;
(3)由于httpd domain被设置为可读取httpd_sys_content_t这个类型的目标文件,因此httpd进程就能够读取在/var/www/html/目录下面的文件了;
(4)最终能否读到/var/www/html/目录下面的数据,还要看rwx是否符合linux权限的规范。
字段 | 模式 | 说明 |
---|---|---|
Enforcing | 强制模式 | 代表SELinux正在运行中,开始限制domain/type。 |
Permissive | 宽容模式 | 代表SELinux正在运行中,不过仅会有警告信息并不会实际限制domain/type的访问。 |
Disabled | 关闭 | SELinux并没有实际运行。 |
查看当前运行模式
[root@server ~]# getenforce
Permissive
设置当前运行模式为强制模式,重启失效
[root@server ~]# setenforce 1
[root@server ~]# getenforce
Enforcing
修改运行模式为permissive,重启不失效
[root@server ~]# vim /etc/selinux/config
SELINUX=permissive
查看当前SELinux的状态
[root@server ~]# sestatus
SELinux status: enabled //开启状态
SELinuxfs mount: /sys/fs/selinux //挂载目录
SELinux root directory: /etc/selinux //配置文件位置
Loaded policy name: targeted //当前策略
Current mode: enforcing //当前模式
Mode from config file: permissive //配置文件读出的模式,即开机生效的模式
Policy MLS status: enabled //灵敏度支持
Policy deny_unknown status: allowed
Max kernel policy version: 28
安全上下文是 SELinux 的核心。
安全上下文我自己把它分为「进程安全上下文」和「文件安全上下文」。
一个「进程安全上下文」一般对应多个「文件安全上下文」。
只有两者的安全上下文对应上了,进程才能访问文件。它们的对应关系由政策中的规则决定。
文件安全上下文由文件创建的位置和创建文件的进程所决定。而且系统有一套默认值,用户也可以对默认值进行设定。
需要注意的是,单纯的移动文件操作并不会改变文件的安全上下文。
在某一目录下创建文件或目录,则创建的文件或目录会继承上一目录的安全上下文的值
1> 使用-Z
选项查看安全上下文
[root@server ~]# ls -Z /var/www/html/ //查看文件或目录的
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html
[root@server ~]# ps auxZ | grep httpd //查看进程的
system_u:system_r:httpd_t:s0 root 5278 0.0 0.1 222024 5088 ? Ss 13:59 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 5317 0.0 0.0 224108 3192 ? S 13:59 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 5318 0.0 0.0 224108 3192 ? S 13:59 0:00 /usr/sbin/httpd -DFOREGROUND
2> 使用chcon
命令修改上下文的值
参数 | 说明 |
---|---|
-R | 递归修改 |
-t | 类型 |
-u | 身份 |
-r | 角色 |
--reference=示例文件 |
将文件的安全上下文按照范例文件修改 |
例如:修改index.html的类型值为httpd_sys_content_t
[root@server html]# chcon -t httpd_sys_content_t index.html
例如:修该index2.html的类型值为index.html的类型值
[root@server html]# chcon --reference index.html index2.html
3> 使用restorecon
命令恢复上下文默认的值
系统默认的目录都有特殊的selinux安全上下文,例如/var/www/html原本就是httpd可以读取的目录。所以如果修改错误可以使用restorecon还原默认的安全上下文。
例如:
[root@server /]# chcon -R -t default_t /var/www/
[root@server /]# ls -Z /var/www/
drwxr-xr-x. root root system_u:object_r:default_t:s0 cgi-bin
drwxr-xr-x. root root system_u:object_r:default_t:s0 html
[root@server /]# restorecon -vR /var/www/ //-R 表示递归,-v表示显示处理过程
restorecon reset /var/www context system_u:object_r:default_t:s0->system_u:object_r:httpd_sys_content_t:s0
restorecon reset /var/www/cgi-bin context system_u:object_r:default_t:s0->system_u:object_r:httpd_sys_script_exec_t:s0
restorecon reset /var/www/html context system_u:object_r:default_t:s0->system_u:object_r:httpd_sys_content_t:s0
restorecon reset /var/www/html/index.html context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
restorecon reset /var/www/html/index2.html context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
[root@server /]# ls -Z /var/www/
drwxr-xr-x. root root system_u:object_r:httpd_sys_script_exec_t:s0 cgi-bin
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 html
4> 使用semanage
命令修改上下文的值
参数 | 说明 |
---|---|
-l | 查询 |
fcontext | 主要用在安全上下文方面 |
port | 用于端口 |
-a | 增加,增加目录的默认安全上下文类型设置 |
-m | 修改 |
-d | 删除 |
-t | 指定类型 |
-p 协议类型 端口号 | 指定端口 |
[root@server /]# semanage fcontext -l | grep -w /web //查看默认type类型
[root@server /]# semanage fcontext -a -t httpd_sys_content_t /web"(/.*)?" //修改默认type类型
[root@server /]# semanage fcontext -l | grep -w /web //再次查看,默认类型已被修改
/web(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
[root@server /]# ls -dZ /web //但此时安全上下文并没有被修改
-rw-r--r--. root root unconfined_u:object_r:etc_runtime_t:s0 /web
[root@server /]# restorecon -R /web //恢复默认安全上下文的值
[root@server /]# ls -dZ /web //此时安全上下文已被修改
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /web
上述命令的意思是:
1.首先查看默认type类型,并没有任何输出
2.修改默认type类型为httpd_sys_content_t
3.再次查看,默认类型已被修改
4.查看此文件夹的安全上下文,但此时安全上下文并没有被修改
5.使用restorecon恢复默认安全上下文的值
6.再次查看此文件夹的安全上下文,此时安全上下文已被修改
也就是说
:
使用chcon命令只会修改文件或目录的安全上下文的值,使用restorecon命令能恢复系统默认记录的值
使用semanage命令修改的是系统默认记录的值,然后使用restorecon命令来恢复默认的值达到目的
应注意两个命令的实现方法不同
使用semanage修改默认值,并使用restorecon恢复默认值达到修改安全上下文的值的意义在于:
若后期需要把某些文件复制或移动到web这个目录下,需要重新修改这些文件的安全上下文的值,使用chcon就比较费事了,如果之前使用了semanage设置了默认值,这时只需要使用restorecon 恢复一下web这个目录即可
案例一:开启防火墙,开启selinux,实现http虚拟目录的访问
配置虚拟目录访问
[root@server /]# vim /etc/httpd/conf.d/vhost.conf
<Directory /http>
AllowOverride none
Require all granted
</Directory>
<VirtualHost 192.168.19.101:80>
DocumentRoot /http
ServerName 192.168.19.101
</VirtualHost>
配置防火墙
[root@server /]# firewall-cmd --add-service=http --per
[root@server /]# firewall-cmd --reload
配置selinux
[root@server /]# setenforce 1
创建目录
[root@server /]# mkdir /http
[root@server /]# echo selinux test > /http/index.html
配置selinux安全上下文
[root@server /]# chcon -R --reference /var/www/ /http
[root@server /]# ls -Z /http
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html
重启http服务
[root@server /]# systemctl restart httpd
客户端测试
[root@client ~]# curl 192.168.19.101
selinux test
案例二:在案例一的基础上,实现基于端口的虚拟目录的访问
配置虚拟目录访问,增加配置字段
[root@server /]# vim /etc/httpd/conf.d/vhost.conf
Listen 10000
<VirtualHost 192.168.19.101:10000>
DocumentRoot /http/port
ServerName 192.168.19.101
</VirtualHost>
配置防火墙
[root@server /]# firewall-cmd --add-port=10000/tcp --per
[root@server /]# firewall-cmd --reload
创建目录
[root@server /]# mkdir /http/port
[root@server /]# echo port_selinux test > /http/port/index.html
这里注意的是,因为http文件夹已经有了selinux安全上下文的值,因此在此目录下创建文件夹或目录会继承http文件夹的安全上下文的值
[root@server /]# ls -Z /http/
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 port
[root@server /]# ls -Z /http/port/index.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /http/port/index.html
这里需要注意的是,还必须使用semanage放行端口号
[root@server /]# semanage port -a -t http_port_t -p tcp 10000
[root@server /]# semanage port -l | grep -w 10000
http_port_t tcp 10000, 80, 81, 443, 488, 8008, 8009, 8443, 9000
重启服务
[root@server /]# systemctl restart httpd
客户端测试
[root@client ~]# curl 192.168.19.101:10000
port_selinux test
装包
[root@server ~]# yum install setools-console -y
使用seinfo
命令查询
参数 | 说明 |
---|---|
-t | 列出selinux的所有类型(type)种类; |
-r | 列出selinux的所有角色(role)种类; |
-u | 列出selinux所有身份标识(user)种类; |
-b | 列出所有规则的种类(布尔值)。 |
例如:查询httpd的类型的策略规则
[root@server ~]# seinfo -t | grep httpd
httpd_php_tmp_t
httpd_var_lib_t
httpd_var_run_t
httpd_user_htaccess_t
httpd_sys_content_t
查询到相关的类型或者是布尔值后,想要知道详细的规则时,需要使用sesearch
命令。
参数 | 说明 |
---|---|
-A | 寻找allow规则; |
-s | 主体类型;即主体程序安全上下文类型 |
-t | 目标类型;即目标文件安全上下文类型 |
-b | 布尔值的规则。 |
例如:详细查询目标类型为httpd_sys_content_t的规则
[root@server ~]# sesearch -A -t httpd_sys_content_t | grep httpd_sys_content_t
allow ftpd_t httpd_sys_content_t : dir { getattr search open } ;
allow httpd_t httpd_sys_content_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
//多余信息省略
例如:详细查询主体类型为httpd_t
,目标类型为httpd_sys_content_t
的规则
显示格式:allow 主体程序安全上下文类型 目标文件安全上下文类型
[root@server ~]# sesearch -A -s httpd_t -t httpd_sys_content_t | grep httpd_sys_content_t | grep httpd_t
allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ;
allow httpd_t httpd_sys_content_t : dir { ioctl read getattr lock search open } ;
allow httpd_t httpd_sys_content_t : lnk_file { read getattr } ;
allow httpd_t httpd_sys_content_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
列出目前系统上面的所有布尔值条款
[root@server ~]# getsebool -a
abrt_anon_write --> off
abrt_handle_event --> off
abrt_upload_watch_anon_write --> on
antivirus_can_scan_system --> off
//多余信息省略
列出httpd_enable_homedirs的值
[root@server ~]# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> off
[root@server ~]# getsebool -a | grep httpd_enable_h
httpd_enable_homedirs --> off
设置httpd_enable_homedirs值为1,-P表示直接将设置值写入配置文件
[root@server ~]# setsebool -P httpd_enable_homedirs=1
[root@server ~]# getsebool -a | grep httpd_enable_h
httpd_enable_homedirs --> on
案例一:开启防火墙,开启selinux,实现客户端nfs的挂载
配置nfs
[root@server ~]# vim /etc/exports
/nfs *(rw)
重新加载
[root@server ~]# exportfs -r
创建共享目录
[root@server ~]# mkdir /nfs
[root@server ~]# echo nfs test > /nfs/test.txt
[root@server ~]# chmod o+w /nfs/
配置防火墙
[root@server ~]# firewall-cmd --add-service=nfs --per
[root@server ~]# firewall-cmd --add-service=rpc-bind --per
[root@server ~]# firewall-cmd --add-service=mountd --per
[root@server ~]# firewall-cmd --reload
配置selinux
[root@server ~]# setsebool nfs_export_all_rw on
[root@server ~]# getsebool -a | grep nfs_e
nfs_export_all_ro --> on
nfs_export_all_rw --> on
客户端测试
[root@client ~]# mount 192.168.19.101:/nfs /nfs
[root@client nfs]# cd /nfs
[root@client nfs]# ls
test.txt
[root@client nfs]# touch dd
[root@client nfs]# rm -f dd
[root@client nfs]# cat test.txt
nfs test