SELinux
一、selinux技术详解
SELinux 概述
SELinux,即 Security-Enhanced Linux,意为安全强化的 Linux,由美国国家安全局(NSA)主导开发。开发初衷是防止系统资源被误用。在 Linux 系统中,系统资源的访问均通过程序进行。例如,当/var/www/html/目录的权限被设置为 777 时,所有程序都能访问该目录。若此时 Web 服务器软件已启动,其触发的进程便可以写入该目录,而该进程面向整个互联网提供服务,存在安全风险。为解决这类权限与进程管控问题,NSA 以 Linux 为研究对象,最终将研究成果整合到 Linux 内核中,SELinux 由此诞生。
SELinux 的作用机制
SELinux 本质是一个内核模块,用于设置程序、文件等的访问权限。由于网络服务同样由程序启动,SELinux 能够有效控制网络服务对系统资源的访问,从而为系统安全提供保障。
传统访问控制机制:自主访问控制(DAC)
在传统的 Linux 系统中,文件权限与账号的关系基于自主访问控制(DAC,Discretionary Access Control)模型。当一个进程试图访问文件时,系统会依据进程的所有者或用户组,对比文件的权限设置。若权限检查通过,进程便能访问该文件。但需要注意的是,各种权限设置对 root 用户无效,root 用户可绕过权限限制进行访问。
SELinux 的访问控制机制:强制访问控制(MAC)
SELinux 引入了强制访问控制(MAC,Mandatory Access Control)模型。该模型可以针对特定的进程和文件资源进行精确的权限控制。在 MAC 模型下,即使用户以 root 身份运行,不同进程所获得的权限并非固定为 root 权限,而是取决于进程的具体设置。这使得系统能够基于进程而非用户来控制文件访问,大大增强了系统的安全性。此外,进程不能随意访问系统文件资源,因为每个文件资源都针对不同进程设置了相应的访问权限。
鉴于系统中进程和文件数量庞大,SELinux 提供了一些默认策略(policy)。这些策略包含多个规则,用户可根据实际需求选择是否启用特定的控制规则,灵活配置系统的访问控制策略 。
二、SELinux 的工作原理
SELinux 采用强制访问控制(MAC)机制管理进程,将进程作为控制主体,把进程能否读取的文件资源作为控制目标。
(1)关键概念
- 主体(subject):即进程,是发起资源访问请求的一方。
- 目标(object):指被主体访问的资源,涵盖文件、目录、端口等。
- 策略(policy):鉴于系统中进程和文件数量众多,SELinux 依据不同服务制定基础的访问安全策略。这些策略包含详细的规则(rule),用以规定不同服务对特定资源的访问权限。当前,主要策略类型如下:
- targeted:对网络服务限制较多,对本地服务限制相对较少,为默认策略。
- strict:提供全面且严格的 SELinux 限制。
- 安全上下文(security context):主体能否访问目标,不仅取决于策略设定,主体与目标的安全上下文也必须匹配。
(2)安全上下文详解
通过ls -Z
命令可查看文件的安全上下文。例如:
[root@localhost ~]# 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 home
安全上下文由冒号分隔为四个字段:Identify:role:type:
- 身份标识(Identify):类似账号身份标识,常见类型有:
- root:代表 root 账号身份。
- system_u:表示程序标识,通常用于进程。
- unconfined_u:与普通用户账号相关。
- 角色(role):通过该字段可判断数据属于程序、文件资源还是用户。常见角色有:
- object_r:代表文件或目录等文件资源。
- system_r:代表进程。
- 类型(type):在默认的 targeted 策略中,身份标识和角色字段重要性相对较低,类型字段才是关键。文件和进程对类型的定义有所不同:
- type:用于文件资源。
- domain:用于主体程序。只有当 domain 与 type 相互匹配,程序才能顺利读取文件资源。
- 灵敏度分级:最后一个字段与 MLS 和 MCS 相关,代表灵敏度,常用 s0、s1、s2 等命名,数字越大,灵敏度越高。
(3)访问过程示例
以 httpd 服务为例,使用ll -Zd
命令查看相关文件:
[root@localhost ~]# ll -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/
- 触发
/usr/sbin/httpd
可执行文件,其类型为httpd_exec_t
。 - 该文件使进程具有
httpd
域,SELinux 策略针对此域制定了众多规则,包括可读取的目标资源类型。 - 由于
httpd
域被设定为可读取httpd_sys_content_t
类型的目标文件,因此 httpd 进程能够读取/var/www/html/
目录下的文件。 - 最终能否成功读取
/var/www/html/
目录下的数据,还需符合 Linux 传统权限(rwx)的规定。
三、SELinux 的启动、关闭与查看
(1)SELinux 的三种模式
- enforcing:强制模式,SELinux 正常运行,对 domain/type 进行严格限制。
- permissive:宽容模式,SELinux 运行,但仅产生警告信息,不实际限制 domain/type 的访问。
- disabled:关闭模式,SELinux 未实际运行。
(2)模式与策略查看
- 查看当前模式:使用
getenforce
命令,示例如下:
[root@localhost ~]# getenforce
Enforcing
- 查看当前 SELinux 使用的策略:使用
sestatus
命令,示例如下:
[root@localhost ~]# sestatus
SELinux status: enabled # 是否启用selinux
SELinuxfs mount: /sys/fs/selinux # selinux的相关文件数据挂载点
SELinux root directory: /etc/selinux
Loaded policy name: targeted # 目前的策略
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 31
- 查看 SELinux 的策略配置文件:使用
vim /etc/selinux/config
命令。
(3)模式切换方法
在 enforcing 和 permissive 之间切换,可使用以下命令:
setenforce 0 # 转换成permissive宽容模式
setenforce 1 # 转换成enforcing强制模式
(4)修改安全上下文
- chcon 命令
- 基本格式:
chcon [-R] [-t type] [-u user] [-r role] 文件
- -R:递归修改目录及其子目录的安全上下文。
- -t:指定安全上下文的类型字段。
- -u:指定身份识别。
- -r:指定角色。
- 参考范例文件修改:
chcon [-R] --reference=范例文件 文件
- 基本格式:
- restorecon 命令:
restorecon [-Rv] 文件或目录
- -R:递归修改子目录。
- -v:显示修改过程。
系统将每个目录的默认 SELinux type 类型记录在/etc/selinux/targeted/contexts/
目录内。可使用semanage
命令查询和修改,基本格式如下:
semanage {login|user|port|interface|fcontext|translation} -l
semanage fcontext -{a|d|m} [-frst] file_spec
其中,-l
用于查询,-a
用于添加目录的默认安全上下文设置,-m
用于修改,-d
用于删除。
四、SELinux 对 Linux 服务的影响
实验一:httpd 服务安全上下文值设定
1. 服务端配置:服务端 IP 地址为 192.168.121.131,执行以下操作:
[root@localhost ~]# systemctl disable firewalld --now
[root@localhost ~]# getenforce
Enforcing
[root@localhost ~]# vim /etc/httpd/conf.d/host.conf
<directory /www>
allowoverride none
require all granted
</directory>
<virtualhost 192.168.121.131:80>
documentroot /www/80
servername 192.168.121.131
</virtualhost>
[root@localhost ~]# mkdir -pv /www/80
[root@localhost ~]# echo this is 80 > /www/80/index.html
[root@localhost ~]# systemctl restart httpd
通过客户端测试,只能访问到 http 服务的测试界面。
2. 修改自定义目录的安全上下文:
[root@localhost ~]# chcon -t httpd_sys_content_t /www/ -R
[root@localhost ~]# chcon -R --reference=/var/www/html /www
修改后即可成功访问。
实验二:web 服务端口改变时的端口设定
1. 修改配置文件:
[root@localhost ~]# vim /etc/httpd/conf.d/host.conf
<directory /www>
allowoverride none
require all granted
</directory>
listen 8888
<virtualhost 192.168.121.131:8888>
documentroot /www/8888
servername 192.168.121.131
</virtualhost>
[root@localhost ~]# mkdir /www/8888
[root@localhost ~]# echo this is 8888 > /www/8888/index.html
[root@localhost ~]# systemctl restart httpd
服务重启失败,通过tail -f /var/log/messages
查看日志。
2. 添加 8888 端口为服务端口:
[root@localhost ~]# semanage port -a -t http_port_t -p tcp 8888
[root@localhost ~]# systemctl restart httpd
测试可访问成功。