SELinux上下文策略管理

SELinux 的策略与规则管理相关命令:seinfo 、sesearch 、getsebool、setsebool、semanage。
semanage 用于查询与修改 SELinux 的安全上下文。

semanage语法

semanage {import,export,login,user,port,ibpkey,ibendport,interface,module,node,fcontext,boolean,permissive,dontaudit} ....
semanage {login|user|port|interface|fcontext|translation} -l
semanage fcontext -{a|d|m} [-frst] file_spec

选项

import      导入本地定制
export      输出本地定制的内容
login       管理linux用户和SELinux限制用户之间的登录映射关系
user        管理SELinux限制的用户(SELinux用户的角色和级别)。
port        管理网络端口类型定义
ibpkey      管理infiniband ibpkey类型定义
ibendport   管理infiniband终端端口类型定义
interface   管理网络接口类型定义
module      管理SELinux策略模块
node        管理网络节点类型定义
fcontext    管理文件上下文映射定义
boolean     管理布尔运算以选择性地启用功能
permissive  管理进程类型执行模式
dontaudit   禁用/启用策略中的捐赠审计规则


fcontext 常用指令:
-a: 增加
-d: 删除
-e: 相等
-l: 查询
-m: 修改
-t: 类型

常用操作

查询安全上下文

# 查询所有安全上下文
sudo semanage fcontext -l

# 查看文件的安全上下文
ls -Z

# 查看目录的安全上下文
ls -Zd /root

# 查看进程的安全上下文
ps auxZ | grep httpd

# 查询 `/usr/share/nginx/html` 目录的安全标记
sudo semanage fcontext -l | grep '/usr/share/nginx/html'
sudo ls -Zdl /usr/share/nginx/html

安全上下文使用 : 分隔为 5 个字段,最后一个 类别 字段是可选的,如下:

system_u:system_r:httpd_t:s0:[类别]
身份字段 :角色    :类型   :灵敏度:[类别]

身份字段(user):用于标识该数据被哪个身份所拥有,相当于权限中的用户身份。

角色(role):用来表示此数据是进程还是文件或目录。

常见的角色有以下两种:

object_r:代表该数据是文件或目录,这里的 _r 代表 role

system_r:代表该数据是进程,这里的 _r 代表 role

类型(type):类型字段是安全上下文中最重要的字段,进程是否可以访问文件,主要就是看进程的安全上下文类型字段是否和文件的安全上下文类型字段相匹配,如果匹配则可以访问。

注意,类型字段在文件或目录的安全上下文中被称作类型(type),但是在进程的安全上下文中被称作域(domain)。也就是说,在主体(Subject)的安全上下文中,这个字段被称为域;在目标(Object)的安全上下文中,这个字段被称为类型。域和类型需要匹配(进程的类型要和文件的类型相匹配),才能正确访问。

灵敏度:灵敏度一般是用 s0、s1、s2 来命名的,数字代表灵敏度的分级。数值越大,代表灵敏度越高。

类别:类别字段不是必须有的,所以我们使用 ls 和 ps 命令查询的时候并没有看到类别字段。但是我们可以通过 seinfo 命令来查询 seinfo -u -x

# 列出SELinux中所有的身份(user)
seinfo -u
# 列出SELinux中所有的角色(role)
seinfo -r
# 列出SELinux中所有的类型(type)
seinfo -t

设置上下文

由SELinux导致的服务启动失败时:

systemctl status nginx   # 得到的报错关键信息如下
nginx: [emerg] bind() to 0.0.0.0:8181 failed (13: Permission denied)

查询 httpd 的安全上下文

semanage port -l | grep http
http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
http_cache_port_t              udp      3130
http_port_t                    tcp      3000, 8000, 80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t            tcp      5988

更改端口 8181 的 SELinux 标记类型使其与端口 80 相同

semanage port -a -t http_port_t -p tcp 8181

再次启动 Nginx

systemctl start nginx

比较安全上下文

matchpathcon /etc /root
/etc    system_u:object_r:etc_t:s0
/root   system_u:object_r:admin_home_t:s0

/web 目录的 SELinux 类型改为与 /var/www/html 目录相同的类型

semanage fcontext -a -e /var/www/html /web
# 比较安全上下文
matchpathcon /var/www/html /web
/var/www/html    system_u:object_r:httpd_sys_content_t:s0
/web    system_u:object_r:httpd_sys_content_t:s0

递归重新标记 /web 目录,使目录下的所有文件都同步标记

restorecon -Rv /web
semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"
restorecon -Rv /web

ValueError: Port tcp/5000 already defined

sudo semanage port -a -t http_port_t -p tcp 5000 若出现类似以下到错误

ValueError: Port tcp/5000 already defined

可使用以下命令修改

sudo semanage port -m -t http_port_t -p tcp 5000