介绍
在这个实验(Lab)中,你将学习如何在 Red Hat Enterprise Linux (RHEL) 上通过管理 SELinux 策略和防火墙规则来保护 Apache Web 服务器 (httpd)。你将通过一个实际的场景来操作,配置 httpd 监听一个非标准端口,并探索 SELinux 和防火墙系统如何管理此类配置的安全性。这个练习提供了在 RHEL 环境中进行常见安全管理任务的实践经验。
你将首先配置 httpd 服务在自定义端口上运行,并观察它在 SELinux 强制执行下的行为。你将使用 semanage 命令来理解和管理 SELinux 端口标签,确保适当的安全合规性。然后,你将使用 firewall-cmd 在系统的防火墙中打开这个自定义端口。最后,你将验证 Web 服务器是否可访问,确认你的安全配置已正确应用。
在自定义端口上配置 httpd 并理解 SELinux 上下文
在这一步,你将学习如何配置 Apache Web 服务器 (httpd) 在一个非标准端口上运行,并理解 SELinux 如何管理端口访问。我们将使用端口 8081,并探索 SELinux 端口管理,即使服务在某些配置中成功启动。
必要的软件包 (httpd, policycoreutils-python-utils 和 firewalld) 已经在设置阶段安装完毕。policycoreutils-python-utils 软件包提供了 semanage 命令,你将在后面的步骤中使用它。
让我们从修改默认的 httpd 配置开始,使其监听一个非标准端口 8081。httpd 的主配置文件位于 /etc/httpd/conf/httpd.conf。我们将使用 nano 编辑器来更改监听端口。
sudo nano /etc/httpd/conf/httpd.conf
在 nano 编辑器中,使用箭头键向下滚动并找到显示 Listen 80 的行。将此行更改为:
Listen 8081
要保存文件并退出 nano,请按 Ctrl+X,然后按 Y 确认更改,最后按 Enter 写入文件。
现在,配置已更改,让我们尝试启动 httpd 服务。在这个容器化环境中,systemctl 不可用。我们将直接启动 httpd 守护进程。
sudo /usr/sbin/httpd
你可能会看到关于服务器完全限定域名(fully qualified domain name)的警告消息,但这很正常,可以忽略。
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using fe80::216:3eff:fe02:1a1e%eth0. Set the 'ServerName' directive globally to suppress this message
让我们通过检查 httpd 进程来验证服务是否正在运行。
ps aux | grep httpd
你应该看到多个 httpd 进程正在运行,这表明 Web 服务器已成功启动。
root 4813 0.0 0.2 23364 7736 ? Ss 09:32 0:00 /usr/sbin/httpd
apache 4814 0.0 0.1 23020 5092 ? S 09:32 0:00 /usr/sbin/httpd
apache 4815 0.0 0.4 1441064 14620 ? Sl 09:32 0:00 /usr/sbin/httpd
apache 4816 0.0 0.5 1441064 18736 ? Sl 09:32 0:00 /usr/sbin/httpd
apache 4837 0.0 0.4 1572200 16872 ? Sl 09:32 0:00 /usr/sbin/httpd
labex 4996 0.0 0.0 6408 2176 pts/3 S+ 09:32 0:00 grep --color=auto httpd
我们还检查 httpd 错误日志,看看启动期间发生了什么。
sudo tail /var/log/httpd/error_log
你应该看到正常的启动消息,表明服务器正在正常运行。
[Tue Jun 17 09:32:46.374275 2025] [core:notice] [pid 4812:tid 4812] SELinux policy enabled; httpd running as context system_u:system_r:unconfined_service_t:s0
[Tue Jun 17 09:32:46.377265 2025] [suexec:notice] [pid 4812:tid 4812] AH01232: suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[Tue Jun 17 09:32:46.394284 2025] [lbmethod_heartbeat:notice] [pid 4813:tid 4813] AH02282: No slotmem from mod_heartmonitor
[Tue Jun 17 09:32:46.399433 2025] [mpm_event:notice] [pid 4813:tid 4813] AH00489: Apache/2.4.62 (Red Hat Enterprise Linux) configured -- resuming normal operations
[Tue Jun 17 09:32:46.399458 2025] [core:notice] [pid 4813:tid 4813] AH00094: Command line: '/usr/sbin/httpd'
有趣的是,httpd 服务在没有任何 SELinux 问题的的情况下启动了。让我们检查审计日志中是否有任何 SELinux 拒绝。
sudo grep AVC /var/log/audit/audit.log | grep httpd
如果没有结果,这意味着 SELinux 没有阻止 httpd 服务绑定到端口 8081。这可能是因为:
- 在某些配置中,端口 8081 默认可能已经允许用于 HTTP 服务
- httpd 进程可能在未受限的上下文中运行
- 端口 8081 可能已经在 SELinux 策略中定义
让我们检查当前的 SELinux 模式:
getenforce
你应该看到 SELinux 处于 "Enforcing" 模式,这意味着它正在积极地强制执行策略。httpd 成功启动的事实表明,端口 8081 可能已经具有适当的 SELinux 标签,或者服务正在未受限的上下文中运行,如日志消息所示。为了本次学习练习的目的,让我们继续下一步,在那里我们将探索 SELinux 端口管理并确保正确的配置。
使用 semanage 理解和管理 SELinux 端口标签
在这一步,你将学习如何使用 semanage 命令管理 SELinux 端口标签。即使 httpd 服务当前正在端口 8081 上运行,理解如何正确配置 SELinux 端口策略以确保安全性和合规性也很重要。你将探索当前的端口配置,并学习如何显式地将正确的 SELinux 类型分配给自定义端口。
首先,你需要找到 Web 服务器端口的正确 SELinux 类型。semanage port -l 命令列出 SELinux 知道的所有端口定义。我们可以将此输出通过管道传递给 grep 以查找与 http 相关的类型。
sudo semanage port -l | grep http
输出显示了几个端口类型。与标准 Web 服务器最相关的是 http_port_t。
http_cache_port_t tcp 8080, 8118, 8123, 10001-10010
http_cache_port_t udp 3130
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t tcp 5988
pegasus_https_port_t tcp 5989
如你所见,http_port_t 被分配给标准 HTTP/HTTPS 端口,如 80 和 443。SELinux 策略允许具有 httpd_t 类型(我们的 Web 服务器)的进程绑定到任何标记为 http_port_t 的端口。让我们检查端口 8081 是否已在此列表中。
请注意,端口 8081 当前未在 http_port_t 下列出。但是,在某些 RHEL 配置中,此端口可能已在 SELinux 策略中定义。让我们尝试使用 semanage port -a 命令显式添加它以实现正确的 SELinux 合规性。
-a选项表示“添加(add)”。-t http_port_t选项指定要分配的类型。-p tcp选项指定协议。
sudo semanage port -a -t http_port_t -p tcp 8081
你可能会看到一条消息,指示“Port tcp/8081 already defined, modifying instead”,这意味着该端口已经配置。这解释了为什么 httpd 在上一步中成功启动。要验证当前配置,请再次列出 http_port_t 定义。
sudo semanage port -l | grep '^http_port_t'
你现在应该看到端口 8081 包含在列表中。
http_port_t tcp 8081, 80, 81, 443, 488, 8008, 8009, 8443, 9000
通过显式更新 SELinux 策略,端口 8081 现在被正式确认为 HTTP 端口。httpd 服务应该继续运行,没有任何问题,并且你已经确保了正确的 SELinux 合规性。
让我们验证该进程是否仍在运行:
ps aux | grep httpd
你应该继续看到多个 httpd 进程,这表明 Web 服务器正在使用正确的 SELinux 端口标签成功运行。
root 4813 0.0 0.2 23364 7736 ? Ss 09:32 0:00 /usr/sbin/httpd
apache 4814 0.0 0.1 23020 5092 ? S 09:32 0:00 /usr/sbin/httpd
apache 4815 0.0 0.4 1441064 14620 ? Sl 09:32 0:00 /usr/sbin/httpd
apache 4816 0.0 0.5 1441064 18736 ? Sl 09:32 0:00 /usr/sbin/httpd
apache 4837 0.0 0.4 1572200 16872 ? Sl 09:32 0:00 /usr/sbin/httpd
labex 5215 0.0 0.0 6408 2176 pts/3 S+ 09:33 0:00 grep --color=auto httpd
你已成功配置 SELinux 策略,以显式允许 httpd 服务在端口 8081 上运行,从而确保了正确的安全合规性。
使用 firewall-cmd 在防火墙中开放自定义端口
在这一步,你将配置系统的防火墙,以允许外部连接到你的 Web 服务器上的自定义端口 8081。尽管由于 SELinux 策略的更改,httpd 服务现在运行正常,但管理网络流量规则的 firewalld 服务默认情况下很可能阻止在此非标准端口上的传入请求。
firewalld 软件包已在设置阶段安装完毕。但是,我们需要首先启动 firewalld 服务。让我们检查当前状态,并在需要时启动它。
sudo firewall-cmd --list-all
如果你看到“FirewallD is not running”,我们需要启动 firewalld 守护进程。在这个容器环境中,我们直接启动 firewalld 守护进程。末尾的 & 在后台运行该进程。
sudo /usr/sbin/firewalld &
稍等片刻,让服务初始化,然后验证它是否正在运行:
sudo firewall-cmd --list-all
现在你应该看到默认区域(public)的当前防火墙配置。
让我们使用 curl 从命令行测试对 Web 服务器的访问。此命令尝试连接到端口 8081 上的 localhost。
curl http://localhost:8081
你应该看到你的测试页面的 HTML 内容,这意味着 Web 服务器可以在本地访问。这是预期的,因为 firewalld 默认情况下通常允许 localhost 流量。
但是,对于外部访问和正确的安全配置,我们仍然需要为我们的自定义端口正确配置防火墙。虽然 localhost 连接通常无论防火墙规则如何都有效,但来自其他机器的外部连接如果没有正确的防火墙配置将被阻止。
首先,让我们检查默认区域(public)的当前规则:
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0 eth1
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
现在,添加一个新规则以允许端口 8081 上的 TCP 流量。在执行此命令之前,请确保 firewalld 正在运行。
--add-port=8081/tcp指定要打开的端口和协议。--permanent确保规则在重启或防火墙重新加载后仍然存在。
sudo firewall-cmd --permanent --add-port=8081/tcp
如果你看到“FirewallD is not running”,请确保你在上一步中启动了 firewalld 守护进程,并稍等片刻让其初始化。
当 firewalld 正常运行时,该命令应返回 success。
success
永久规则在重新加载之前不会应用于活动的防火墙配置。让我们重新加载防火墙以应用我们的新规则。
sudo firewall-cmd --reload
此命令也应返回 success。
success
让我们通过再次列出规则来验证端口是否已打开。
sudo firewall-cmd --list-all
你现在应该在 ports: 部分看到 8081/tcp。
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0 eth1
sources:
services: cockpit dhcpv6-client ssh
ports: 8081/tcp
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
你已成功配置防火墙。最后一步是测试你是否可以访问 Web 服务器。
验证标准和自定义 Web 服务器端口的访问
在最后一步,你将验证你所做的所有更改是否确保你的 Web 服务器已正确配置,以便进行本地和外部访问。你已经配置了 SELinux 策略并在防火墙中打开了必要的端口。现在,你将执行全面的测试以确认配置。
首先,让我们创建一个简单的测试页面,以便当我们连接时,我们得到一个自定义消息。httpd 的默认文档根目录是 /var/www/html。我们将在该目录中创建一个 index.html 文件。你需要 sudo 权限才能写入此位置。
echo "Success! Web server on custom port 8081 is working." | sudo tee /var/www/html/index.html
此命令将成功消息放入 index.html 文件中。这里使用 tee 命令是因为它允许我们使用管道写入需要 sudo 权限的文件。你应该看到消息回显到终端作为确认。
Success! Web server on custom port 8081 is working.
为了完成练习,让我们通过尝试访问标准 HTTP 端口 80 来演示对比。由于我们的服务器配置为仅侦听 8081,因此此请求应该失败。
curl http://localhost:80
正如预期的那样,连接被拒绝,因为没有服务在侦听该端口。
curl: (7) Failed to connect to localhost port 80: Connection refused
这证实了你的服务器仅在你配置的自定义端口上运行。通过这个实验,你已经学习了 RHEL 上服务的关键故障排除工作流程:
- 检查服务状态和日志。
- 调查审计日志中的 SELinux 拒绝。
- 使用
semanage纠正 SELinux 策略。 - 使用
firewall-cmd配置防火墙规则。 - 验证连接。
总结
在这个实验中,你学习了如何在自定义端口上配置 Web 服务器并管理 SELinux 安全策略。通过预先安装的 Apache Web 服务器(httpd)、policycoreutils-python-utils 和 firewalld 软件包,你专注于理解 SELinux 端口管理和防火墙配置。你修改了 httpd.conf 文件,将 Web 服务器的监听端口更改为非标准端口 8081。
你发现 httpd 服务在自定义端口上成功启动,因为端口 8081 已经在 SELinux 策略中正确配置。这提供了一个探索 SELinux 端口管理并了解 semanage 如何工作以维护正确端口标签的机会。你还学习了使用 firewall-cmd 来管理防火墙规则,确保安全合规性和可访问性。即使 httpd 在未受限的上下文中运行,本实验也演示了为生产环境正确配置 SELinux 和防火墙的重要性。



