介绍
在本实验中,你将学习如何通过管理 SELinux 策略和防火墙规则,来加固 Red Hat Enterprise Linux (RHEL) 上的 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 守护进程。
设置阶段已经禁用了默认的 SSL 虚拟主机,因此这个纯 HTTP 实验可以在没有无关证书文件错误的情况下启动。
sudo /usr/sbin/httpd
你可能会看到一条关于服务器完全限定域名(FQDN)的警告消息,这是正常的,可以忽略。
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 进程可能在无限制(unconfined)上下文中运行。
- 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」(端口 tcp/8081 已定义,改为修改),这意味着该端口之前已经配置过了。这解释了为什么 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 在防火墙中开放自定义端口
在这一步中,你将配置系统防火墙,以允许外部连接到你在自定义端口 8081 上的 Web 服务器。尽管由于 SELinux 策略的更改,httpd 服务现在运行正常,但管理网络流量规则的 firewalld 服务默认很可能会阻止此非标准端口上的传入请求。
firewalld 软件包已在设置阶段安装。但是,我们需要先启动 firewalld 服务。让我们检查当前状态,并在需要时启动它。
sudo firewall-cmd --list-all
如果你看到「FirewallD is not running」(FirewallD 未运行),我们需要启动 firewalld 守护进程。在此容器环境中,我们直接启动 firewalld 守护进程。末尾的 & 将进程放入后台运行。
sudo /usr/sbin/firewalld &
稍等片刻让服务初始化,然后验证它是否正在运行:
sudo firewall-cmd --list-all
现在你应该能看到默认区域(public)的当前防火墙配置。
让我们使用 curl 从命令行测试对 Web 服务器的访问。此命令尝试连接到 localhost 的 8081 端口。
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 和防火墙配置的重要性。



