在 RHEL 中使用 firewalld 和 SELinux 进行安全加固

红帽企业 LinuxBeginner
立即练习

介绍

在本实验中,你将学习如何通过管理 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 端口管理,即使在某些配置下服务能够成功启动。

必要的软件包(httpdpolicycoreutils-python-utilsfirewalld)已在设置阶段安装完毕。policycoreutils-python-utils 软件包提供了 semanage 命令,你将在后续步骤中使用它。

让我们首先修改默认的 httpd 配置,使其监听非标准端口 8081httpd 的主配置文件位于 /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 端口。原因可能是:

  1. 在某些配置中,8081 端口可能默认已允许 HTTP 服务使用。
  2. httpd 进程可能在无限制(unconfined)上下文中运行。
  3. 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 端口,如 80443。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 服务器的访问。此命令尝试连接到 localhost8081 端口。

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 上服务故障排除的关键工作流程:

  1. 检查服务状态和日志。
  2. 在审计日志中调查 SELinux 拒绝记录。
  3. 使用 semanage 纠正 SELinux 策略。
  4. 使用 firewall-cmd 配置防火墙规则。
  5. 验证连接性。

总结

在本实验中,你学习了如何将 Web 服务器配置在自定义端口上,并管理 SELinux 安全策略。借助预装的 Apache Web 服务器 (httpd)、policycoreutils-python-utilsfirewalld 软件包,你重点了解了 SELinux 端口管理和防火墙配置。你修改了 httpd.conf 文件,将 Web 服务器的监听端口更改为非标准端口 8081。

你发现 httpd 服务在自定义端口上成功启动,因为 8081 端口已经在 SELinux 策略中正确配置。这为你提供了一个探索 SELinux 端口管理并了解 semanage 如何维护正确端口标签的机会。你还学习了如何使用 firewall-cmd 管理防火墙规则,确保了安全合规性和可访问性。尽管 httpd 在无限制上下文中运行,但本实验演示了在生产环境中进行正确的 SELinux 和防火墙配置的重要性。