Linux

httpd 与 SELinux

RHEL 9 搭 Apache httpd,用 firewalld 放行端口,并读懂 SELinux 安全上下文;附「网页打不开」三层排查。

「服务装好了,网页却打不开」——十有八九不是 httpd 配错了目录,而是 防火墙没放行 或 SELinux 拦了标签。这一篇用一条最小 Web 实验,把三层一次跑通。

系列:从 RHCSA 到 RHCE · 第 12 / 17 篇 上一篇:服务与计划任务 下一篇:Podman 容器 总目录:系列索引

环境说明

  • 系统:RHEL 9
  • 身份:root
  • 网络:另一台机器或宿主机能访问本机 IP(示例 192.168.56.20)
  • 前置:服务与计划任务(systemctl)

三层模型(先记住这个)

浏览器访问 http://IP/ 时,请求要连过三关:

① httpd 进程在跑、目录里有网页
        ↓
② 防火墙允许 80(或你改的端口)
        ↓
③ SELinux 允许 httpd 读这些文件、占这个端口
层典型命令常见症状
应用systemctl status httpd连接被拒绝、打不开
防火墙firewall-cmd --list-all浏览器转圈、超时
SELinuxls -Z / getenforce403、改端口后起不来

下面按「先搭通 → 再挡防火墙 → 再踩 SELinux」学习。

1. 安装并启动 httpd

dnf -y install httpd
systemctl enable httpd --now
systemctl status httpd

默认关键配置(可用 VIM 查看,不必一次全懂):

less /etc/httpd/conf/httpd.conf
配置项常见默认含义
Listen 8080监听端口
DocumentRoot "/var/www/html"该目录网页根目录

默认网页目录:

ls /var/www/html

2. 放一个测试页

echo 'hello from rhel9' > /var/www/html/index.html
cat /var/www/html/index.html

本机自测(不经过外网防火墙路径时也有用):

curl http://127.0.0.1/
curl http://localhost/

应看到 hello from rhel9。

从另一台机器访问:

curl http://192.168.56.20/
# 或用浏览器打开 http://192.168.56.20/

若本机 curl 127.0.0.1 成功、远端失败——先查防火墙。

3. 防火墙 firewalld

是什么

firewalld 按「服务名 / 端口」决定外网能不能进来。装了 httpd 不等于自动放行 80。

查看

systemctl status firewalld
firewall-cmd --list-all

看 services:、ports: 里有没有 http 或 80/tcp。

放行 http 服务(推荐,语义清晰)

firewall-cmd --add-service=http --permanent
firewall-cmd --reload
firewall-cmd --list-all
选项含义
--add-service=http放行 http 相关端口(通常 80)
--permanent写入配置,重启后仍有效
--reload让当前立即生效
不加 --permanent只影响当前,重启防火墙后可能丢失

也可以直接按端口:

firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --reload

立刻生效(不重启 firewalld 时另一种写法):

firewall-cmd --add-service=http
# 当前会话生效;再补 --permanent 写入配置更稳妥

考点:考试常要求「永久放行」→ 必须 --permanent(或 equivalent),再验证 --list-all。 易错:只 --permanent 不 --reload,当前仍不通。 易错:firewalld 根本没启动,却以为「已放行」;先 systemctl is-active firewalld。

4. SELinux:第二道闸门

它是什么

在用户/组权限之外,RHEL 默认还有一层 强制访问控制:按「程序」和「文件标签」决定能不能访问,不完全看 root。

查看状态:

getenforce
输出含义
Enforcing强制执行(默认,考试常见)
Permissive只警告、不拦截(排障时有用)
Disabled关闭(一般不推荐生产关闭)

配置文件(改完通常要重启才切换模式):

less /etc/selinux/config

文件安全上下文(标签)

每个文件有 SELinux 上下文,ls -Z 可见:

ls -Zd /var/www/html/
ls -Z /var/www/html/index.html

示例:

system_u:object_r:httpd_sys_content_t:s0 /var/www/html/

httpd_sys_content_t 表示:这类标签允许 httpd 读取作网页内容。

实验:从「不对的目录」放网页

echo 'hello from wrong label' > /root/hello.html
ls -Z /root/hello.html

上下文多半是 admin_home_t 之类,不是 httpd_sys_content_t。

拷到网页目录(注意:mv 可能保留旧标签):

cp /root/hello.html /var/www/html/hello.html
# 若直接 mv,标签可能仍是 admin_home_t:
# mv /root/hello.html /var/www/html/hello.html
ls -Z /var/www/html/hello.html

cp 到正确目录后,新文件常能继承目录类型;若仍是旧标签,浏览器访问 http://IP/hello.html 可能 403。

改标签:chcon

chcon -t httpd_sys_content_t /var/www/html/hello.html
# 目录可递归:
chcon -R -t httpd_sys_content_t /var/www/html/
ls -Z /var/www/html/hello.html

再访问应正常。

考点:「内容在正确目录却 403」→ 查 ls -Z,用 chcon 改到 httpd_sys_content_t。 说明:生产里更推荐 restorecon 按策略恢复默认标签;考试按题面用 chcon 即可。

实验:改端口被 SELinux 拦住

默认 httpd 用 80。改成 82 试试:

vim /etc/httpd/conf/httpd.conf
# 将 Listen 80 改为 Listen 82
systemctl restart httpd

常见失败:

Job for httpd.service failed ...

原因:82 端口没有 http_port_t 标签,SELinux 不让 httpd 用。

查看已允许的 http 端口:

semanage port -l | grep http

semanage 可能未安装:

dnf -y install policycoreutils-python-utils
semanage port -l | grep http

放行 82:

semanage port -a -t http_port_t -p tcp 82
# 若已存在同类型条目需修改,用 -m 而不是 -a
systemctl restart httpd
ss -lnt | grep 82

防火墙也要放行新端口:

firewall-cmd --add-port=82/tcp --permanent
firewall-cmd --reload

访问:

curl http://192.168.56.20:82/

易错:只改 Listen 82 和防火墙,忘记 semanage port。 易错:-a 时端口已存在会报错,按提示改用 -m 修改。

5. 「网页打不开」排查清单

按顺序,不要跳:

  1. httpd 活着吗 systemctl is-active httpd
  2. 本机 curl 通吗 curl -I http://127.0.0.1/
  3. 网页文件在吗 ls /var/www/html/;DocumentRoot 是否仍是该目录
  4. 防火墙 firewall-cmd --list-all 是否含 http 或对应端口
  5. SELinux 模式 getenforce
  6. 文件标签 ls -Z 是否为 httpd_sys_content_t;不对则 chcon
  7. 非 80 端口 semanage port -l | grep http;防火墙是否放行该 port
# 一键自检(实验机)
systemctl is-active httpd firewalld
curl -sI http://127.0.0.1/ | head -1
firewall-cmd --list-all
getenforce
ls -Zd /var/www/html

排查决策(简图)

本机 curl 失败? → 查 httpd / 端口 / DocumentRoot
本机成功、外网失败? → 查防火墙
403? → 查 SELinux 标签(chcon)
改端口起不来? → semanage port + 防火墙

6. 推荐完整实验(约 30 分钟)

# 1) 装并启动
dnf -y install httpd
systemctl enable httpd --now
echo 'hello from rhel9' > /var/www/html/index.html
curl http://127.0.0.1/

# 2) 防火墙
firewall-cmd --list-all
firewall-cmd --add-service=http --permanent
firewall-cmd --reload
firewall-cmd --list-all
# 远端再 curl / 浏览器访问

# 3) SELinux 标签
echo 'x' > /root/t.html
ls -Z /root/t.html
cp /root/t.html /var/www/html/t.html
ls -Z /var/www/html/t.html
# 若标签不对:
chcon -t httpd_sys_content_t /var/www/html/t.html
curl http://127.0.0.1/t.html

# 4)(可选)改 82 端口
# vim Listen 82
# semanage port -a -t http_port_t -p tcp 82
# firewall-cmd --add-port=82/tcp --permanent && firewall-cmd --reload
# systemctl restart httpd

7. 速查表

目标命令
装/启 Webdnf -y install httpd;systemctl enable httpd --now
网页根目录/var/www/html
本机测试curl http://127.0.0.1/
看防火墙firewall-cmd --list-all
永久放行 httpfirewall-cmd --add-service=http --permanent + --reload
SELinux 状态getenforce
看标签ls -Z 文件
改标签chcon -t httpd_sys_content_t 路径
端口标签semanage port -a/-m -t http_port_t -p tcp 82

考点与易错

考点:httpd 起服务 + 写 index;防火墙 --permanent 放行;SELinux chcon / semanage port。 易错:--permanent 后不 --reload。 易错:用 mv 从家目录挪网页文件,标签仍是 admin_home_t 导致 403。 易错:改 Listen 非标准端口却不改 SELinux 端口类型。 练习环境:课堂若用 blue 做 Web,IP 与题面一致即可;三层命令相同。

小结

  1. Web 三层:httpd → 防火墙 → SELinux,一层一层查。
  2. 防火墙永久放行:--add-service=http --permanent 再 --reload。
  3. SELinux:ls -Z 看标签,chcon -t httpd_sys_content_t;改端口用 semanage port。
  4. 本机 curl 127.0.0.1 成功、外网失败时,优先怀疑防火墙。

下一篇用 Podman 跑容器,并处理卷挂载时的 SELinux :Z。


系列导航:总目录 · 上一篇:服务与计划任务 · 下一篇:Podman 容器

相关阅读

全部文章 →
← 返回列表更多「Linux」