11.2. 问题最多的三种原因
以下小节描述了问题的主要三个原因:标记问题、为服务配置布尔值和端口,以及不断发展的 SELinux 规则。
11.2.1. 标记问题
在运行 SELinux 的系统上,所有进程和文件都标有包含安全相关信息的标签。此信息称为 SELinux 上下文。如果这些标签错误,则可能会拒绝访问。标记不正确的应用可能会导致向其进程分配不正确的标签。这会导致 SELinux 拒绝访问,并且进程可能会创建标记错误的文件。
标记问题的常见原因是,当服务使用非标准目录时。例如,管理员想要使用
/srv/myweb/
,而不是在网站中使用 /var/www/html/
。在 Red Hat Enterprise Linux 中,/srv
目录使用 var_t
类型进行标记。在 /srv
中创建的文件和目录继承这个类型。另外,顶层目录中新创建的对象(如 /myserver
)可以使用 default_t
类型进行标记。SELinux 会阻止 Apache HTTP 服务器(httpd
)访问这两个类型。要允许访问,SELinux 必须知道 /srv/myweb/
中的文件可以被 httpd
访问:
~]#
semanage fcontext -a -t httpd_sys_content_t "/srv/myweb(/.*)?"
此 semanage 命令会将
/srv/myweb/
目录(以及其下的所有文件和目录)的上下文添加到 SELinux 文件上下文配置中[8].semanage
程序不会更改上下文。以 root 用户身份运行 restorecon
工具以应用更改:
~]#
restorecon -R -v /srv/myweb
有关在 file-context 配置中添加上下文的更多信息,请参阅 第 4.7.2 节 “持久性更改:semanage fcontext”。
11.2.1.1. 什么是正确的上下文?
matchpathcon
程序检查文件路径的上下文,并将其与该路径的默认标签进行比较。以下示例演示了在包含错误标记文件的目录中使用 matchpathcon
:
~]$
matchpathcon -V /var/www/html/*
/var/www/html/index.html has context unconfined_u:object_r:user_home_t:s0, should be system_u:object_r:httpd_sys_content_t:s0
/var/www/html/page1.html has context unconfined_u:object_r:user_home_t:s0, should be system_u:object_r:httpd_sys_content_t:s0
在本例中,
index.html
和 page1.html
文件使用 user_home_t
类型进行标识。这种类型用于用户主目录中的文件。使用 mv 命令从您的主目录移动文件可能会导致文件使用 user_home_t
类型进行标记。这个类型不应存在于主目录之外。使用 restorecon
实用程序将这些文件恢复到其正确类型:
~]#
restorecon -v /var/www/html/index.html
restorecon reset /var/www/html/index.html context unconfined_u:object_r:user_home_t:s0->system_u:object_r:httpd_sys_content_t:s0
要恢复目录中所有文件的上下文,请使用
-R
选项:
~]#
restorecon -R -v /var/www/html/
restorecon reset /var/www/html/page1.html context unconfined_u:object_r:samba_share_t:s0->system_u:object_r:httpd_sys_content_t:s0
restorecon reset /var/www/html/index.html context unconfined_u:object_r:samba_share_t:s0->system_u:object_r:httpd_sys_content_t:s0
有关
matchpathcon
的详细示例,请参阅 第 4.10.3 节 “检查默认 SELinux 上下文”。
11.2.2. 受限服务如何运行?
服务可以以多种方式运行。为了满足此需求,您需要指定如何运行您的服务。这可以通过布尔值来实现,允许在运行时更改 SELinux 策略的部分,而不必知晓编写 SELinux 策略。这允许更改,例如允许服务访问 NFS 卷,而无需重新加载或重新编译 SELinux 策略。另外,在非默认端口号中运行服务需要使用 semanage 命令来更新策略配置。
例如,要允许 Apache HTTP 服务器与 MariaDB 通信,请启用
httpd_can_network_connect_db
布尔值:
~]#
setsebool -P httpd_can_network_connect_db on
如果特定服务无法访问,请使用
getsebool
和 grep
实用程序查看是否有布尔值可用于访问。例如,使用 getsebool -a | grep ftp 命令搜索 FTP 相关布尔值:
~]$
getsebool -a | grep ftp
ftpd_anon_write --> off
ftpd_full_access --> off
ftpd_use_cifs --> off
ftpd_use_nfs --> off
ftpd_connect_db --> off
httpd_enable_ftp_server --> off
tftp_anon_write --> off
如需布尔值列表以及是否处于打开状态,请运行 getsebool -a 命令。对于布尔值列表,请说明每个布尔值是什么,以及是否以 root 用户身份运行 semanage boolean -l 命令。有关列出和配置布尔值的详情,请查看 第 4.6 节 “布尔值”。
端口号
根据策略配置,服务只能在某些端口号中运行。尝试更改服务在没有更改策略的情况下运行的端口可能会导致服务无法启动。例如,以 root 用户身份运行 semanage port -l | grep http 命令,以列出
http
相关端口:
~]#
semanage port -l | grep http
http_cache_port_t tcp 3128, 8080, 8118
http_cache_port_t udp 3130
http_port_t tcp 80, 443, 488, 8008, 8009, 8443
pegasus_http_port_t tcp 5988
pegasus_https_port_t tcp 5989
http_port_t
端口类型定义了 Apache HTTP 服务器可以侦听的端口,本例中为 TCP 端口 80、443、488、8008、8009 和 8443。如果管理员配置了 httpd.conf
,以便 httpd
侦听端口 9876(Listen 9876
),但没有更新策略来反应这一点,以下命令会失败:
~]#
systemctl start httpd.service
Job for httpd.service failed. See 'systemctl status httpd.service' and 'journalctl -xn' for details.
~]#
systemctl status httpd.service
httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled)
Active: failed (Result: exit-code) since Thu 2013-08-15 09:57:05 CEST; 59s ago
Process: 16874 ExecStop=/usr/sbin/httpd $OPTIONS -k graceful-stop (code=exited, status=0/SUCCESS)
Process: 16870 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)
类似于以下内容的 SELinux 拒绝消息会记录到
/var/log/audit/audit.log
:
type=AVC msg=audit(1225948455.061:294): avc: denied { name_bind } for pid=4997 comm="httpd" src=9876 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=system_u:object_r:port_t:s0 tclass=tcp_socket
~]#
semanage port -a -t http_port_t -p tcp 9876
a
选项
添加新记录; -t
选项定义类型; -p
选项定义协议。最后的参数是要添加的端口号。
11.2.3. 演进规则和损坏的应用程序
应用程序可能会损坏,从而导致 SELinux 拒绝访问。另外,SELinux 规则会不断演变 - SELinux 可能没有了解某个应用程序会以某种特定方式运行,因此即使应用程序按预期工作,也有可能出现拒绝访问的问题。例如,如果 PostgreSQL 的新版本发布,它可能会执行之前没有看到过的当前策略的操作,从而导致访问被拒绝,即使应该允许访问。
对于这样的情形,在访问被拒绝后,使用
audit2allow
实用程序创建自定义策略模块以允许访问。有关使用 audit2allow
的信息,请参阅 第 11.3.8 节 “允许访问: audit2 允许”。