一、实验环境(rhel7.0版本)
主机环境:rhel7.0
各主机信息
主机名 | IP |
---|---|
server | 172.25.254.1 |
二、SELinux介绍
SELinux 是【Security Enhanced Linux】的英文缩写,字面上的意义就是安全强化的 Linux 之意。
SELinux 是在进行进程、文件等详细配置时依据的一个内核模块。
SELinux 引入了强制访问控制(MAC)的方法。强制访问控制很有趣,它可以针对特定的进程与特定的文件资源来管理权限。也就是说,即使你是 root,那么在使用不同的进程时,你所能获取的权限也并不一定是 root,而是根据当时该进程的设置而定。
这里,再额外介绍一下传统的文件权限与帐号的关系:自主访问控制(DAC)
- 我们知道系统的帐号主要分为系统管理员(root)与一般用户,而这两种身份能否使用系统上面的文件资源则与 rwx 的权限设置有关。不过,你要注意的是,各种权限设置对 root 是无效的。因此,当某个进程想要对文件进行读写时,系统就会根据该进程的拥有者和用户组,比对文件的权限,只有通过权限检查,才可以读写该文件。
- 这种读写文件系统的方式被称为【自主访问控制——DAC】。基本上,就是依据进程的拥有者与文件资源的 rwx 权限来决定有无读写的权限。
三、SELinux的运行模式
再次重复说明一下,SELinux 是通过 MAC 的方式来管理进程的。它控制的主体是进程,而目标则是该进程能否读取的【文件资源】,所以先来说明一下这些东西的相关性。
- 主体(Subject):SELinux 主要管理的就是进程,因此你可以将【主体】与【进程】划上等号;
- 目标(Object):主体进程能否读写的【目标资源】一般就是文件系统,因此你可以将【目标选项】与【文件系统】划上等号;
- 策略(Policy):在目前的 Redhat 7.x 里面仅提供三个主要的策略,分别是:
- targeted:针对网络服务限制较多,针对本及限制较少,是默认的策略。
- minium:由 target 自定义而来,仅针对选择的进程来保护。
- mls:完整的 SELinux 限制,限制方面较为严格。
建议使用默认的 targeted 策略即可。
四、SELinux 安全上下文的介绍及查看
1、安全上下文的介绍
上面我们谈到了主体、目标与策略。除了策略指定之外,主体与目标的安全上下文必须一致才能顺利读写。
可以将这个安全上下文当作 SELinux 内必备的 rwx。
安全上下文是放置在文件的 inode 内的,因此主体进程想要读取目标文件资源时,同样需要读取 inode,这 inode 内就可以比对安全上下文以及 rwx 等权限值是否正确,而给予适当的读写权限依据。
2、安全上下文的查看
查看安全上下文可使用【ls -Z】(注意:你必须已经启动了 SELinux 才行)
[root@server ~]# ls -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
-rw-r--r--. root root system_u:object_r:admin_home_t:s0 initial-setup-ks.cfg
如上所示,安全上下文主要用冒号分为三个字段,这三个字段的意义为:
user: role: type
身份识别 角色 类型
下面详细说明一下这三个字段的意义:
- 身份识别(user):主要的身份识别有下面几种常见的类型:
- unconfined_u:不受限的用户,也就是说,该文件来自不受限的进程。一般来说,我们使用可登录帐号获取 bash 之后,默认的 bash 环境是不受 SELinux 管制的,因此,如果是我们用户通过 bash 自己建立的文件,大多则是不受限的 unconfined_u 身份。
- system_u:系统用户,大部分就是系统自己产生的文件。如果是系统或软件本身所提供的文件,大多就是 system_u 这个身份名称;如果是网络服务所产生的文件,或是系统服务运行过程产生的文件,则大部分的识别就会是 system_u。
- 角色(role):通过角色字段,我们可以知道这个数据是属于进程、文件资源还是代表用户,一般的角色有:
- object_r:代表的是文件或目录资源,这应该是最常见的。最后面使用【-r】来结尾,因为是 role 的意思。
- system_r:代表的就是进程,不过,一般用户也会被指定成为 system_r。最后面使用【-r】来结尾,因为是 role 的意思。
- 类型(type):在默认的 targeted 策略中,Identify 与 Role 字段基本上是不重要的,重要的是这个类型(type)字段。基本上,一个主体进程能不能读取到这个文件资源与类型字段有关,而类型字段在文件与进程方面的定义又不太相同,分别是:
- type:在文件资源(Object)上面称为类型(Type)
- domain:在主体进程(Subject)则称为域(Domain)。domain 需要与 type 搭配,则该进程才能够顺利读取文件资源
例子:
在默认的 target 策略下,其实最重要的字段是类型字段(type),主体与目标之间是否具有可以读写的权限,与进程的 domain 及文件的 type 有关。这两者的关系我们可以使用 crond 以及它的配置文加来说明。即通过 /usr/bin/crond、/etc/crontab、/etc/crond.d 等文件来说明。首先,先看看这几个东西的安全上下文内容:
1、先看看 crond 这个【进程】的安全上下文内容
[root@server ~]# ps -eZ | grep crond
system_u:system_r:crond_t:s0-s0:c0.c1023 539 ? 00:00:00 crond
system_u:system_r:crond_t:s0-s0:c0.c1023 541 ? 00:00:00 atd
# 这个安全上下文的类型名称为 crond_t
2、再来看看执行文件、配置文件等的安全上下文的内容是什么
[root@server ~]# ll -Zd /usr/sbin/crond /etc/cron.d /etc/crontab /var/spool/cron/
drwxr-xr-x. root root system_u:object_r:system_cron_spool_t:s0 /etc/cron.d
-rw-r--r--. root root system_u:object_r:system_cron_spool_t:s0 /etc/crontab
-rwxr-xr-x. root root system_u:object_r:crond_exec_t:s0 /usr/sbin/crond
drwx------. root root system_u:object_r:user_cron_spool_t:s0 /var/spool/cron/
上面的内容,我们可以通过如下的方式来解读:
- 首先,我们触发一个可执行的目标文件,即具有 crond_exec_t 这个类型的 /usr/sbin/crond 文件
- 该文件的类型会让这个文件所造成的主体进程(Subject)具有 crond_t 这个类型的crond 这个域(domain)
- 由于 crond domain 被设置为可以读取 system_crond_spool_t 和 user_cron_spoll_t 这两种类型的配置文件,因此你的配置文件放到 /etc/cron.d/ 目录下,就能够被 crond 那个进程所读取了。
- 但最终能不能读到正确的数据,还是要看 rwx 是否符合 Linux 权限的规范。
上述的流程告诉我们几个重点,
- 策略内需要制定详细的 domain/type 相关性;
- 若文件的 type 设置错误,那么即使权限设置为 rwx 全开的 777,该进程也无法读取目标文件资源;
- rwx 需要符合 Linux 权限的规范。
五、SELinux 3种模式的介绍、运行状态及查看
1、SELinux 3种模式的介绍
目前 SELinux 依据启动与否,共有 3 种魔术,分别如下:
- Enforcing:强制模式,代表 SELinux 运行中,且已经正确开始限制 domain/type。
- Permissive:警告模式,代表 SELinux 运行中,不过仅会有警告信息并不会实际限制 domain/type 的读写(警告信息的查看:cat /var/log/audit/audit.log)。这种模式可以用来作为 SELinux 的 debug 之用。
- Disabled:关闭模式,SELinux 并没有实际运行。
我们要知道,并不是所有的进程都会被 SELinux 所管制。那么如何查看有没有首先(confined)?很简单,可以通过 【ps -eZ】去查看。举例来说,我们来找一找 crond 与 bash 这两个进程是否被限制吧?
[root@server ~]# ps -eZ | grep -E 'crond|bash'
system_u:system_r:crond_t:s0-s0:c0.c1023 541 ? 00:00:00 atd
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 1461 pts/0 00:00:00 bash
system_u:system_r:crond_t:s0-s0:c0.c1023 3325 ? 00:00:00 crond
我们直接看第三个字段的数据。我们可以看到,crond 确实是受限的主体进程,而 bash 是本机进程,就是不受限(unconfined_t)的类型。
2、SELinux 3种模式的运行状态
- 如果是 Disabled 模式,那么 SELinux 将不会运行,当然受限的进程也不会经过 SELinux ,也时直接去判断 rwx。不会有警告信息。
- 如果是 Permissive 模式,这种模式也时不会组织主体进程,不过万一没有通过策略规则或安全上下文的比对时,那么该读写操作将会被记录起来(/var/log/audit/audit.log),可作为未来检查问题的判断依据。会有警告信息。
- 如果是 Enforcing 模式,就是实际将受限主体进入规则对比,安全上下文比对的流程,若失败,就直接阻止主体进程的读写操作,并且将它记录下来(/var/log/audit/audit.log)。如果通通没有问题,这才进入 rwx 权限的判断。会有警告信息。
3、SELinux 3种模式的查看
[root@server ~]# getenforce
Enforcing <==显示出目前的模式是 Enforcing
六、SELinux 的策略的查看
sestatus [-vb]
选项与参数:
-v:检查位于 /etc/sestatus.conf 内的文件与进程的安全上下文内容
-b:将目前策略的规则布尔值列出,亦即某些规则(rule)是否要启动(0/1)之意
[root@server ~]# sestatus
SELinux status: enabled <==是否要启动 SELinux
SELinuxfs mount: /sys/fs/selinux <==SELinux 的相关文件挂载点
SELinux root directory: /etc/selinux <==SELinux 的根目录所在
Loaded policy name: targeted <==SELinux 目前的策略是什么
Current mode: enforcing <==目前的模式
Mode from config file: enforcing <==目前配置文件内规范的模式
Policy MLS status: enabled <==是否含有 MLS 的模式机制
Policy deny_unknown status: allowed <==是否默认阻止未知的主体进程
Max kernel policy version: 28
如上所示,目前是启动的而且是 Enforcing 模式,而由配置文件查询得知亦为 Enforcing 模式。此外,目前的默认策略为 targeted。那 SELinux 的配置文件是那个文件?其实就是 /etc/sysconfig/selinx 或 /etc/selinux/config。下面,我们来看看内容:
[root@server ~]# vim /etc/selinux/config
7 SELINUX=enforcing <==调整 enforcing、disabled、permissive
12 SELINUXTYPE=targeted <==目前仅有 targeted、mls、minimum 三种策略
七、SELinux 3种模式之间的切换
关闭模式和其他两种模式之间的切换(永久设定),必须重启系统(reboot),才能生效
警告模式和强制模式之间的切换(临时设定),不需要重启系统(reboot),立即生效
但是,警告模式和强制模式之间的切换(永久设定),需要重启系统(reboot),才能生效
如果临时设定和永久设定的selinux状态不同的时候,如果没有重启电脑,因为临时设定是立即生效,而永久设定需要重启系统之后才能生效,所以,此时,临时设定的优先级要高一些
在某些特殊的情况下,你从 Disabled 切换成 Enforcing 之后,竟然有一堆服务无法顺利启动,都会跟你说在 /lib/xxx 里面的数据没有权限读取,所以启动失败。这大多是重新写入 SELinux 类型(Relabel)出错之故,使用 Permissive 就没有这个错误。那如何处理呢?最简单的方法就是在 Permissive 的状态下,使用【restorecon -Rv】重新还原所有 SELinux 的类型,就能够解决这个问题。
1、临时设定(只针对强制状态和警告状态之间的切换)
系统重启之后,又会恢复为原来的selinux状态
setenforce [0|1]
选项与参数:
0:转成 Permissive 警告模式
1:转成 Enforcing 强制模式
【1】、setenforce 0 将selinux设置为警告状态(Permissive)
【2】、setenforce 1 将selinux设置为强制状态(Enforcing)
2、永久设定
编辑配置文件 /etc/sysconfig/selinux 或 /etc/selinux/config
八、SELinux 策略内的规则管理
我们知道 SELinux 的三种模式会影响到主体进程的放行与否。如果是进入 Enforcing 模式,那么接着下来会影响到主体进程的,当然就是第二关:【target 策略内的各项规则(rules)】。那么我们怎么知道目前这个策略里面到底有多少会影响主体进程的规则呢?很简单,通过 getsebool 来看一看即可。
1、SElinux 各个规则的布尔值查询 getsebool
要查询系统上面全部规则的启动与否(on/off,即布尔值),通过 sestatus -b 或 getsebool -a 均可。
getsebool [-a] [规则的名称]
选项与参数:
-a:列出目前系统上面的所有 SELinux 规则的布尔值状态
# 值的注意的是: -a 与 规则的名称 不能同时出现
【1】、范例一:列出目前系统上面的所有 SELinux 规则的布尔值状态
[root@server ~]# getsebool -a
abrt_anon_write --> off
abrt_handle_event --> off
abrt_upload_watch_anon_write --> on
...(中间省略)...
httpd_enable_homedirs --> off
...(中间省略)...
zoneminder_anon_write --> off
zoneminder_run_sudo --> off
# 这么多的 SELinux 规则,每个规则后面都列出现在水允许放行还是不允许放行的布尔值
【2】、范例二:查询 httpd_enable_homedirs 这个规则的状态
[root@server ~]# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> off
2、SELinux 各个规则的主体进程能够读取的文件 SELinux 类型查询 seinfo、sesearch
我们现在知道有这么多的 SELinux 规则,但是每个规则内到底是在限制什么东西?如果你想要知道的话,就要使用 seinfo 等工具。这些工具某人没有安装,需要自己手动安装。
(1)seinfo命令
### 安装支持 seinfo 和 sesearch 命令的软件包
[root@server ~]# yum whatprovides seinfo
...(省略)...
setools-console-3.3.7-46.el7.x86_64 : Policy analysis command-line tools for SELinux
...(省略)...
[root@server ~]# yum install setools-console-3.3.7-46.el7.x86_64 -y
seinfo [-urtb]
选项与参数:
-u:列出 SELinux 的所有身份识别(user)种类
-r:列出 SELinux 的所有角色(role)种类
-t:列出 SELinux 的所有类型(type)种类
-b:列出所有规则的种类(布尔值)
【1】、范例一:列出 SELinux 在此策略下的统计状态
从上面,我们可以看到这个策略 SELinux Type 共有 4446个;而针对网络服务地规则 (Booleans) 共制定了 280 条规则
(2)sesearch命令
如果你想要查询目前所由的身份识别与角色,使用【seinfo -u】及【seinfo -r】就可以知道了。至于简单的统计数据,直接输入【seinfo】即可。但是上面还是没有探单规则相关的东西。例如,我们想查看 crond 这个进程的安全上下文 crond_t 能够读取的文件 SELinux 类型有哪些?就需要使用 sesearch 命令了。
sesearch [-A] [--all] [-s 主体类型] [-t 目标类型][-b 布尔值]
选项与参数:
-A:列出后面数据中,允许【读取或放行】的相关信息
--all:列出该类别或布尔值地所有相关信息
-s:后面还要接类型,例如 -s crond_t
-t:后面还要接类型,例如 -t httpd_sys_content_t
-b:后面还要接 SELinux 的规则,例如 -b httpd_enable_ftp_server
【1】、范例一:找出 crond_t 这个主体进程能够读取的文件 SELinux 类型
[root@server ~]# sesearch -A -s crond_t | grep spool
allow crond_t var_spool_t : file { ioctl read getattr lock open } ;
allow crond_t var_spool_t : dir { ioctl read getattr lock search open } ;
allow daemon user_cron_spool_t : file { ioctl read write getattr lock append } ;
allow crond_t system_cron_spool_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
allow crond_t system_cron_spool_t : dir { ioctl read getattr lock search open } ;
allow crond_t cron_spool_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
allow crond_t cron_spool_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow crond_t user_cron_spool_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
allow crond_t user_cron_spool_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow crond_t user_cron_spool_t : lnk_file { read getattr } ;
allow crond_t system_cron_spool_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
allow crond_t user_cron_spool_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
# allow 后面接主体进程以及文件的 SELinux 类型
# 意思是说,crond_t 可以读取 system_cron_spool_t 、user_spoll_t 的文件/目录类型
【2】范例二:我们来查一查,getsebool -a 里面看到的 httpd_enable_homedirs 到底是什么?又是规范了哪些主体进程能够读取的 SELinux 类型呢?
[root@server ~]# semanage boolean -l | grep httpd_enable_homedirs
httpd_enable_homedirs (off , off) Allow httpd to enable homedirs
# httpd_enable_homedirs 的功能是允许 httpd 进程去读取使用者家目录里的意思
[root@server ~]# sesearch -A -b httpd_enable_homedirs
Found 43 semantic av rules:
allow httpd_suexec_t autofs_t : dir { ioctl read getattr lock search open } ;
allow httpd_suexec_t cifs_t : file { ioctl read getattr lock execute execute_no_trans open } ;
allow httpd_suexec_t cifs_t : dir { ioctl read getattr lock search open } ;
...(下面省略)...
# 从上面的数据才可以理解,在这个规则中,主要是放行 httpd_t 能否读取使用者家目录的文件。
# 所以,如果这个规则没有启动,基本上,httpd_t 这种进程就无法读取使用者家目录下的文件。
3、修改 SELinux 规则的布尔值 setsebool——永久修改
SELinux布尔值是更改SELinux的开关;有时候,SELinux的访问权限可选可通过SELinux布尔值触发,可以提高系统安全性。
setsebool [-p] [规则名称] [0|1]或[off|on]
选项与参数:
-P:直接将设置值写入配置文件,该设置信息未来会生效的。
【1】、范例一:查询 httpd_enable_homedirs 这个规则的状态,并且修改这个规则成为不同的布尔值
[root@server ~]# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> off <==结果是 off,依题意给它启动看看
[root@server ~]# setsebool -P httpd_enable_homedirs 1 #会跑很久很久,请耐心等待
[root@server ~]# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> on
值的注意的是:setsebool 一定要加上 -P 的选秀爱嗯,因为这样才能将此设置写入配置文件。
【2】、范例二:对 vsftpd 服务进行配置,允许本地用户可以上传文件
[root@server ~]# getsebool -a | grep ftp
ftp_home_dir --> off
(1)getsebool -a | grep ftp 显示布尔值,查看功能的开启或关闭状态
可以看到vsftpd服务的某些功能是默认关闭的
ftp_home_dir-------> off 表示本地用户上传文件的功能没有开启
测试:本地用户上传不允许
(2)setsebool -P ftp_home_dir on 开启本地用户的上传功能
(3)getsebool -a | grep ftp 再次查看功能的开启或关闭状态
测试:本地用户可以上传文件
九、SELinux 安全上下文的修改——永久修改
我们知道 SELinux 对受喜爱男的主体进程有没有影响,
- 第一关考虑 SELinux 的三种模式;
- 第二关考虑 SELinux 的策略规则(sebool 值);
- 第三关则是开始比对 SELinux 类型。
1、范例一:将 /etc/hosts 复制到 root 用户主目录,并查看相关的 SELinux 类型变化
[root@server ~]# cp /etc/hosts /root/
[root@server ~]# ll -Zd /etc/hosts /root/hosts /root/
-rw-r--r--. root root system_u:object_r:net_conf_t:s0 /etc/hosts
dr-xr-x---. root root system_u:object_r:admin_home_t:s0 /root/
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /root/host
2、范例一:将 /root/hosts 剪切到 /opt 用户主目录,并查看相关的 SELinux 类型变化
[root@server ~]# mv /root/hosts /opt/
[root@server ~]# ll -Zd /opt/hosts /opt/
drwxrwxrwx. root root system_u:object_r:usr_t:s0 /opt/
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /opt/hosts
# 看到了吗?当单纯地复制时,SELinux 的 Type 类型是会继承目标目录,所以 /root/hosts 地类型会变成admin_home_t 这个类型了。
# 但是如果是移动呢?那么连同 SELinux 地类型也会被移动过去,因此 /opt/hosts 会依旧报出 admin_home_t 而不会变成 usr_t 这个类型。
1、使用 chcon 手动修改目录/文件的 SELinux 类型
chcon [-R] [-t type] [-u user] [-r role] [-v] 文件
chcon [-R] --reference=范例文件 文件
选项与参数:
-R:连同该目录下的子目录也同时修改
-t:后面接安全上下文的类型栏位,例如 httpd_sys_content_t
-u:后面接身份识别,例如 system_u。(不重要)
-r:后面接角色,例如system_r。(不重要)
-v:若有变化成功,请将变动的结果列出来。
【1】、范例一:查询一下 /etc/hosts 的 SELinux 类型,并将该类型套用到新建的文件 file上
【2】、范例二:直接以 /etc/shadow 的 SELinux 类型套用到文件file上
【3】、范例一:查询一下 /etc/hosts 的 SELinux 类型,并将该类型套用到新建的目录 dir 及其dir目录中的所有内容上
2、使用 restorecon 让文件恢复正确的 SELinux 类型
restorecon [-RvF] 文件或目录
选项与参数:
-R:连同子目录一起修改
-v:将过程显示到屏幕
-F:强制修改安全上下文
【1】、范例一:将 /var/www/html/file 恢复成默认的 SELinux 类型
同理,可以使用命令“restorecon -RvvF /var/www/html/”将 /var/www/html 下面的文件通通恢复成默认的 SELinux 类型。
3、semanage 默认目录的安全上下文的查询与修改
你应该觉得奇怪,为什么 restorecon 可以【恢复】原本的 SELinux 类型呢?那肯定是有个地方在记录每个文件/目录的 SELinux 默认类型?没错,是这样,其内容记录在 /etc/selinux/targeted/contexts/files/下。 那要(1)如何查询默认的 SELinux 类型以及(2)如何增加/修改/删除默认的 SELinux 类型呢?很简单,通过 semanage 即可。
semanage [login|user|port|interface|fcontext|translation] -l
semanage fcontext [-a|d|m] [-frst] file_spec
选项与参数:
fcontext:主要硬杂安全上向艾文方面的用途,-l 为查询的意思
-a:增加的意思,你可以增加一些目录的默认安全上下文类型的设置
-m:修改的意思
-d:删除的意思
【1】、范例一:证明为什么命令 restorecon -RVVF /var/www/html/file 可以将文件 /var/www/html/file 的安全上下文修改为 system_u:object_r:httpd_sys_content_t:s0
【2】、范例二:新建一个目录 /test,并将该目录的安全上下文的 type 类型修改为 samba_share_t
[root@server ~]# mkdir /test
[root@server ~]# ll -Zd /test/
drwxr--r--. root root unconfined_u:object_r:default_t:s0 /test/
[root@server ~]# semanage fcontext -a -t samba_share_t '/test(/.*)?' <== 修改 /test 目录的安全上下文
[root@server ~]# cat /etc/selinux/targeted/contexts/files/file_contexts.local
# This file is auto-generated by libsemanage
# Do not edit directly.
/test(/.*)? system_u:object_r:samba_share_t:s0
# 其实就是记录在这个文件的
[root@server ~]# restorecon -RvvF /test/ <==尝试恢复默认值
restorecon reset /test context unconfined_u:object_r:default_t:s0->system_u:object_r:samba_share_t:s0
[root@server ~]# ll -Zd /test/
drwxr--r--. root root system_u:object_r:samba_share_t:s0 /test/
值的一提的是,使用 semanage 命令修改完安全上下文之后,必须要使用 restorecon 命令进行刷新才能使修改的安全上下文生效。不能像 chcon 命令,chcon 命令修改完安全上下文之后,立即生效。