Security-Enhanced Linux 安全增强型 Linux,它是一个 Linux 内核模块,也是 Linux 的一个安全子系统。
SELinux 主要作用就是最大限度地减小系统中服务进程可访问的资源。
1、自主访问控制(DAC)
主体是用户。在没有使用 SELinux 的操作系统中,决定一个资源是否能被访问的因素是:某个资源是否拥有对应用户的权限(读、写、执行)。所以只要访问这个资源的进程符合以上的条件就可以被访问。但是root 用户不受任何管制,系统上任何资源都可以无限制地访问。
2、强制访问控制(MAC)
主体是进程。在使用了 SELinux 的操作系统中,决定一个资源是否能被访问的因素除了上述因素之外,还需要判断每一类进程是否拥有对某一类资源的访问权限。即使进程是以 root 身份运行的,也需要判断这个进程的类型以及允许访问的资源类型才能决定是否允许访问某个资源。进程的活动空间也可以被压缩到最小。如果程序出了漏洞,影响范围也只在其允许访问的资源范围内,安全性大大增加。 MAC 又细分为了两种方式,一种叫类别安全(MCS)模式,另一种叫多级安全(MLS)模式。
下文中的操作均为 MCS 模式。
在 DAC 模式下,只要相应目录有相应用户的权限,就可以被访问。而在 MAC 模式下,还要受进程允许访问目录范围的限制。
1、主体(Subject)
可以完全等同于进程。
2、对象(Object)
被主体访问的资源。可以是文件、目录、端口、设备等。
3、 政策和规则(Policy & Rule)
系统中哪些进程需要管制、要怎么管制是由政策决定的。一套政策里面有多个规则。部分规则可以按照需求启用或禁用(以下把该类型的规则称为布尔型规则)。
规则是模块化、可扩展的。在安装新的应用程序时,应用程序可通过添加新的模块来添加规则。用户也可以手动地增减规则。大致有三套政策,分别是:
1)targeted:对大部分网络服务进程进行管制。这是系统默认使用的政策(下文均使用此政策)。
2)minimum:以 targeted 为基础,仅对选定的网络服务进程进行管制。一般不用。
3)mls:多级安全保护。对所有的进程进行管制。这是最严格的政策,配置难度非常大。一般不用,除非对安全性有极高的要求。政策可以在 /etc/selinux/config 中设定。
4、安全上下文(Security Context)
安全上下文是 SELinux 的核心。
安全上下文我自己把它分为「进程安全上下文」和「文件安全上下文」。
一个「进程安全上下文」一般对应多个「文件安全上下文」。
只有两者的安全上下文对应上了,进程才能访问文件。它们的对应关系由政策中的规则决定。
文件安全上下文由文件创建的位置和创建文件的进程所决定。而且系统有一套默认值,用户也可以对默认值进行设定。
注意:单纯的移动文件操作并不会改变文件的安全上下文。
安全上下文有四个字段,分别用冒号隔开。
形如:system_u:object_r:admin_home_t:s0
这条语句通过:划分成了四段,第一段 system_u 代表的是用户,第二段 object_r 表示的是角色,第三段是SELinux中最重要的信息,admin_home 表示的是类型,最后一段 s0 是跟MLS、MCS相关的东西,暂时不需要管。
①system_u指的是SElinux用户,root表示root账户身份,user_u表示普通用户无特权用户,system_u表示系统进程,通过用户可以确认身份类型,一般搭配角色使用。身份和不同的角色搭配时有权限不同,虽然可以使用su命令切换用户但对于SElinux的用户并没有发生改变,账户之间切换时此用户身份不变,在targeted策略环境下用户标识没有实质性作用。
②object_robject_r一般为文件目录的角色、system_r一般为进程的角色,在targeted策略环境中用户的角色一般为system_r。用户的角色类似用户组的概念,不同的角色具有不同的身份权限,一个用户可以具备多个角色,但是同一时间只能使用一个角色。在targeted策略环境下角色没有实质作用,在targeted策略环境中所有的进程文件的角色都是system_r角色。
③admin_home文件和进程都有一个类型,SElinux依据类型的相关组合来限制存取权限。 Touch /.autorelabel 系统当中默认启用了selinux,去读取一个禁止文件,而这个文件里是否有内容他都要去读,读完之后它会给这些系统默认的文件设置安全值。 |
SELinux 有三种工作模式,分别是:
1、enforcing:强制模式。违反 SELinux 规则的行为将被阻止并记录到日志中。
2、permissive:宽容模式。违反 SELinux 规则的行为只会记录到日志中。一般为调试用。
3、disabled:关闭 SELinux。
级别切换
禁用<-->强制:下次启动生效
禁用<-->警告:下次启动生效
强制<-->警告:即时生效
配置文件
/etc/selinux/config
#查看级别
[root@localhost ~]# getenforce
Enforcing
#使用命令行切换级别
[root@localhost ~]# setenforce 1 #开启
[root@localhost ~]# setenforce 0 #关闭
#修改级别
[root@localhost ~]# vim /etc/selinux/config
SELINUX=enforcing
#查看selinux的状态
[root@localhost ~]# sestatus
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: permissive
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 28
#查看selinux的值
[root@localhost ~]# ll -Z
-rw-------. root root system_u:object_r:admin_home_t:s0 anaconda-ks.cfg
drwxr-xr-x. root root unconfined_u:object_r:admin_home_t:s0 Desktop
drwxr-xr-x. root root unconfined_u:object_r:admin_home_t:s0 Documents
#查看context值的变化
[root@localhost ~]# touch 1
[root@localhost ~]# ll -Z
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 1
[root@localhost ~]# cp 1 /tmp/
[root@localhost ~]# ll -Z /tmp
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 1
;文件的context值会随着目录的作用和环境的不同而发生改变,该值会继承上一级目录的context值
#修改context值
chcon -t context值的类型 文件名 (目录的话加上 -R,表示递归)
[root@localhost ~]# ll -Z
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 1
[root@localhost ~]# chcon -t user_tmp_t 1
[root@localhost ~]# ll -Z
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 1
#恢复context值
[root@localhost ~]# restorecon -v 1
restorecon reset /root/1 context unconfined_u:object_r:user_tmp_t:s0->unconfined_u:object_r:admin_home_t:s0
#查看进程的context值
[root@localhost ~]# ps -Z
LABEL PID TTY TIME CMD
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 12872 pts/1 00:00:00 bash
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 46761 pts/1 00:00:00 ps
[root@localhost ~]# semanage port -l | grep "\b80\b"
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
案例一:使用httpd服务演示context值的设定
#创建http服务的网页目录及文件
[root@localhost ~]# mkdir -pv /www/80
mkdir: created directory ‘/www’
mkdir: created directory ‘/www/80’
[root@localhost ~]# echo 'welcome to 80!' >/www/80/index.html
#修改主服务配置文件
[root@localhost ~]# vim /etc/httpd/conf/httpd.conf
修改 ServerName 192.168.100.160:80 (服务器ip)
#添加主机配置文件
[root@localhost ~]# vim /etc/httpd/conf.d/vhosts.conf
[root@localhost ~]# cat /etc/httpd/conf.d/vhosts.conf
AllowOverride None
Require all granted
DocumentRoot "/www/80"
#如果在重启服务时,日志提示DNS解析失败时,按如下办法解决
[root@localhost ~]#vim /etc/hosts
192.168.100.160 web
#如果有布尔值的提示,请输入以下命令进行处理
[root@localhost ~]#setsebool -P httpd_can_network_relay 1
#在防火墙中添加web服务的放行规则
[root@localhost ~]# firewall-cmd --permanent --add-service=http
success
[root@localhost ~]# firewall-cmd --reload
success
#重启服务
[root@localhost ~]# systemctl restart httpd.service
#通过浏览器进行访问,发现只能访问默认页,无法访问我们自定义的页面
#这时需要修改自定义目录的context值
[root@localhost ~]# chcon -t httpd_sys_content_t /www/ -R
无需重启服务即可访问自定义的页面
案例二:使用web服务端口的改变来演示端口的设定
#创建目录和网页文件
[root@localhost ~]# mkdir /www/8888 -p
[root@localhost ~]# echo 'Welcome to 8888 port!' >/www/8000/index.html
[root@localhost ~]# vim /etc/httpd/conf.d/vhosts.conf
[root@localhost ~]# cat /etc/httpd/conf.d/vhosts.conf
AllowOverride None
Require all granted
LISTEN 8888
DocumentRoot "/www/8888"
#重启服务发现有错误
[root@localhost ~]# 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@localhost ~]# systemctl status httpd -l
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: failed (Result: exit-code) since Mon 2019-05-06 09:14:45 EDT; 18s ago
Docs: man:httpd(8)
man:apachectl(8)
Process: 5675 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=1/FAILURE)
Process: 5672 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)
Main PID: 5672 (code=exited, status=1/FAILURE)
May 06 09:14:44 localhost.localdomain httpd[5672]: (13)Permission denied: AH00072: make_sock: could not bind to address [::]:8888
May 06 09:14:44 localhost.localdomain httpd[5672]: (13)Permission denied: AH00072: make_sock: could not bind to address 0.0.0.0:8888
May 06 09:14:44 localhost.localdomain httpd[5672]: no listening sockets available, shutting down
May 06 09:14:44 localhost.localdomain httpd[5672]: AH00015: Unable to open logs
May 06 09:14:45 localhost.localdomain systemd[1]: httpd.service: main process exited, code=exited, status=1/FAILURE
May 06 09:14:45 localhost.localdomain kill[5675]: kill: cannot find process ""
May 06 09:14:45 localhost.localdomain systemd[1]: httpd.service: control process exited, code=exited status=1
May 06 09:14:45 localhost.localdomain systemd[1]: Failed to start The Apache HTTP Server.
May 06 09:14:45 localhost.localdomain systemd[1]: Unit httpd.service entered failed state.
May 06 09:14:45 localhost.localdomain systemd[1]: httpd.service failed.
#查看进程的context值
[root@localhost ~]# semanage port -l | grep "\b80\b"
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
#添加该自定义端口为服务端口
[root@localhost ~]# semanage port -a -t http_port_t -p tcp 8888
#添加之后查看变化
[root@localhost ~]# semanage port -l | grep "\b80\b"
http_port_t tcp 8888, 80, 81, 443, 488, 8008, 8009, 8443, 9000
#进入web可以访问到网页内容