我刚刚遇到了另一个与 SELinux 相关的问题。看来我haproxy
不允许打开到后端的 TCP 连接,我可以使用 Google 快速修复它。现在,我想知道如果一个人真的知道如何使用 SELinux,将如何解决这个问题?
问题
我想使用 haproxy 将我的可公开访问的端口 5000 转发到 127.0.0.1:5601。我相应地配置了 haproxy,并systemctl restart haproxy
立即在系统日志中看到了这一点:
May 9 09:38:45 localhost haproxy[2900]: Server kibana/app1 is DOWN, reason: Layer4 connection problem, info: "General socket error (Permission denied)", check duration: 0ms. 0 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
permission denied --> SELinux
已经成为我解决 Linux 问题时占主导地位的短路评估。这么多年没有让我失望过!
解决方案
semanage port --add --type http_port_t --proto tcp 5601
因为
SELinux 只允许 Web 服务器与一组有限的端口建立出站连接
显然该semanage
命令将端口 5601 添加到该列表中。这可行了,现在我的 haproxy 为我提供 Kibana 服务。伟大的!
我不明白/不知道的
当我ps fauxZ
看到 haproxy 的上下文是system_u:system_r:haproxy_t:s0
.通过 Linux 上的可用命令,我如何才能发现 haproxy 受到与 关联的端口的限制http_port_t
?
答案1
SELinux 因晦涩难懂而享有盛誉——我认为这是当之无愧的。
按照我的理解,正在运行的程序的上下文定义了当前策略允许其访问或执行的操作。因此,正如您所猜测的,haproxy_t 类型被允许基于 http_port_t 类型的一些权限。
现在让我们尝试实际弄清楚如何找到这种关系。
获取 SELinux 标签
如您所知,ps -eZ
将列出正在运行的进程的 SELinux 标签 - 对于 haproxy,user:role:type:sensitivity
即system_u:system_r:haproxy_t:s0
。重要的是类型,在本例中是 haproxy_t。
权限
现在要找出该类型具有哪些权限,我们可以使用 search[1]:
sesearch -d -A -s haproxy_t
-d
仅显示直接结果 - 如果省略此结果,这还将显示来自seinfo --type=haproxy_t -x
! 的所有对象。-A
搜索允许规则-s haproxy_t
将源类型定义为 haproxy_t
现在我们得到了相当多的结果(在我的 CentOS 7 VM 上有 106 个结果),因为碰巧定义了很多不同的细粒度权限。此时,您需要更多地了解您正在搜索的内容 - 权限适用的类、目标类型或权限名称本身。
按类别搜索
让我们先看类:所以我们知道我们的源类型是haproxy_t
,并且我们认为我们的类可能与互联网有关,所以很有可能它可能是 tcp_socket 。
sesearch -d -A -s haproxy_t -c tcp_socket
这将列出与 tcp_socket 有关的源类型 haproxy_t 的所有允许规则。这大大缩小了范围,但仍然有人猜测其中哪一个可能是我们正在寻找的。
按特定权限搜索
接下来,让我们尝试使用权限 - 我们知道我们需要 haproxy 来绑定和连接特定端口,对吧?所以我们尝试 name_bind 和 name_connect 权限。
sesearch -d -A -s haproxy_t -p "name_bind, name_connect"
Found 4 semantic av rules:
allow haproxy_t http_cache_port_t : tcp_socket { name_bind name_connect } ;
allow haproxy_t commplex_main_port_t : tcp_socket { name_bind name_connect } ;
allow haproxy_t http_port_t : tcp_socket { name_bind name_connect } ;
allow haproxy_t port_type : tcp_socket name_bind ;
这仅显示 4 个结果,其中只有 3 个可能是我们的罪魁祸首!就 SELinux 而言,这些结果是任何具有 haproxy_t 上下文的进程被允许绑定的唯一端口。
按目标类型搜索
这有点作弊,因为在这种情况下我们实际上是在寻找目标类型!但是,为了完整起见 - 例如,如果我们想找出 haproxy_t 从 http_port_t 获得哪些权限,我们可以使用以下内容:
sesearch -d -A -s haproxy_t -t http_port_t
Found 1 semantic av rules:
allow haproxy_t http_port_t : tcp_socket { name_bind name_connect } ;
当然,这只会给我们一个结果以及适用的权限。
港口
现在我们知道了目标对象,并且它们是端口的定义,我们可以准确地找出它们包含哪些端口。好吧,让我们来了解一下:
semanage port -l | grep -E 'http_cache_port_t|commplex_main_port_t|http_port_t'
commplex_main_port_t tcp 5000
commplex_main_port_t udp 5000
http_cache_port_t tcp 8080, 8118, 8123, 10001-10010
http_cache_port_t upd 3130
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t tcp 5988
因此,我们看到 tcp 端口 5601 不在该列表中。现在,就 SELinux 而言,您可以使用命令将该端口添加到任何这些类型semanage port --add --type XXX --proto tcp 5601
,并且它会起作用。但由于这是为 http 提供服务,因此 http_port_t 似乎是最适用的类型。
希望这能稍微揭开它的神秘面纱。
[1] 在 setools-console 包中可用。
答案2
如果您不确定必须配置哪个 SELinux 设置,那么:
安装以下软件包:
yum install setroubleshoot-server
然后运行:
sealert -l /var/log/auditd..
遵循说明/建议。