摘要
当应用程序服务器开始监听端口号时,selinux会检查端口号的安全上下文scontext
类型和程序的源secontext
类型,如果发现程序并没有绑定该端口号的权限,例如发现该端口号只属于保留端口号reserved_port_t
,则会禁止deny
程序绑定端口的操作,导致服务器无法正常启动。此时可以通过semanage来增加需要绑定的端口的secontext
类型,例如给82端口增加类型http_port_t
,这样服务器程序就具有82端口的绑定权限了。
场景及排查
- 使用nginx服务器绑定80,81端口,服务器正常启动,然而绑定82端口,服务器启动失败,查询日志
systemctl status nginx
bash
nginx: [emerg] bind() to 0.0.0.0:82 failed (13: Permission denied)
发现82端口绑定失败了,没有权限
- 进一步排查,首先将selinux设置为宽容模式,看看服务器能否启动
bash
setenforce 0
systemctl start nginx
发现服务器正常启动了,说明刚才是由于selinux的权限未通过导致服务器启动失败的,可以修改selinux配置是它永久处于宽容模式(但不安全),因此继续selinux的排查
- 将selenux 设置回严格模式
setenforce 1
,并检查/var/log/audit/目录下的日志文件,可以发现其中一行:
bash
type=AVC msg=audit(1731871244.866:352): avc:
denied { name_bind } for pid=3291
comm="nginx" src=82
scontext=system_u:system_r:httpd_t:s0
tcontext=system_u:object_r:reserved_port_t:s0
tclass=tcp_socket permissive=0
这条日志是从SELinux(Security-Enhanced Linux)的审计日志中获取的,用于记录系统上的安全策略事件。SELinux是一种安全模块,它为Linux操作系统提供了访问控制安全策略。让我们逐步解析这条日志:
- type=AVC: 这表示这是一条访问矢量缓存(Access Vector Cache)事件,AVC是SELinux用来加速安全策略检查的一种机制。
- msg=audit(xxx:352): 这部分包含了审计消息的时间戳(xxx秒)和序列号(352),用于标识日志事件。
- avc: denied { name_bind }: 这表示SELinux安全策略拒绝了某个操作,这里是name_bind操作,通常与套接字(socket)绑定到特定的名称(如端口号)相关。
- for pid=3291 comm="nginx": 这表示被拒绝的操作是由进程ID(PID)为3291的进程发起的,该进程的命令名为nginx。
- src=82: 这通常指的是尝试绑定的源端口号或相关资源标识符,但在这里可能不直接对应于TCP/UDP端口号(可能是SELinux内部的某种标识符或错误显示),通常这部分需要根据上下文或SELinux的具体实现来解释。
- scontext=system_u:system_r:httpd_t:s0: 这是源安全上下文(source context),包含了用户(system_u)、角色(system_r)、类型(httpd_t)和安全级别(s0)。httpd_t是nginx进程的安全类型,表示它作为Web服务器运行。
- tcontext=system_u:object_r:reserved_port_t:s0: 这是目标安全上下文(target context),同样包含了用户、角色、类型和安全级别。reserved_port_t表示尝试访问或操作的对象(在这个上下文中是TCP端口)是保留给特定用途的。
- tclass=tcp_socket: 这表示被访问或操作的对象类(type class)是TCP套接字。
- permissive=0: 这表示SELinux当前不处于permissive模式。在permissive模式下,SELinux会记录违规操作但不会阻止它们;而在enforcing模式下(如本例所示),SELinux会阻止违规操作并记录它们。
说明82端口具有类型reserved_port_t,nginx无法直接绑定82端口的权限,接下来使用工具semanage查看各个端口的权限情况
- 安装semanage
查看yum provides semanage
的支持清单
bash
yum provides semanage
# 结果示例
policycoreutils-python-utils-3.3-1.oe2203.noarch : Policy core python utilities for selinux
Repo : OS
Matched from:
Filename : /usr/sbin/semanage
安装工具
bash
yum install policycoreutils-python-utils-3.3-1.oe2203.noarch
- 查看selinux端口号的权限
semanage port -l
,可以发现其中几行重要条目
bash
|SELinux 端口类型 |协议 |端口号
|http_port_t |tcp |80, 81, 443, 488, 8008, 8009, 8443, 9000|
|reserved_port_t |tcp |1-511
http_port_t:
- 协议:TCP(传输控制协议)
- 端口号:80, 81, 443, 488, 8008, 8009, 8443, 9000
- 这些端口通常用于HTTP和HTTPS服务。例如,端口80和8008常用于未加密的HTTP流量,而端口443和8443则用于加密的HTTPS流量。其他端口(如81, 488, 9000)也可能被配置为HTTP或HTTPS服务,具体取决于服务器的配置。
reserved_port_t:
- 协议:TCP
- 端口号:1-511
- 这些端口被称为"保留端口"或"系统端口",通常用于重要的系统服务。由于这些端口号较低,它们被认为是特权端口,只有具有特定权限(通常是root权限)的进程才能绑定到这些端口。这种限制是为了防止未经授权的服务占用这些关键端口,从而可能干扰系统的正常运行。
其中80,81等端口同时具有http_port_t和reserved_port_t类型,nginx可以正常绑定http_port_t类型的端口80,81,而无法绑定只具有reserved_port_t类型的82端口
6.使用semanage为端口添加权限
为82端口添加类型http_port_t
bash
semanage port -a -t http_port_t -p tcp 82
# -a 表示添加操作,-t http_port_t 指定了目标类型,-p tcp 指定了协议(TCP),82 是要添加的端口号
小结
通过为82端口添加类型http_port_t,可以看到,http_port_t中就多了个端口号82,此时再启动服务器,就不会看到权限错误的信息了