记一次 Nginx 多站点配置踩坑实录:路由串台与 SELinux 403 拦截排查(Rocky9)

📅 2026/8/3 10:36:31 👁️ 阅读次数 📝 编程学习
记一次 Nginx 多站点配置踩坑实录:路由串台与 SELinux 403 拦截排查(Rocky9)

记一次 Nginx 多站点配置踩坑实录:路由串台与 SELinux 403 拦截排查

一、 故障背景与环境

  • 操作系统:Rocky Linux 9
  • Web 服务:Nginx 1.20.1
  • 目标架构:配置基于域名的虚拟主机。
    • 访问专属域名mytest.com➡️ 返回默认站点(/usr/share/nginx/html)。
    • 访问其他任意域名或直接使用 IP 访问 ➡️ 返回自定义的兜底站点(/var/www/default)。

二、 故障一:路由“串台”(所有请求均返回默认欢迎页)

1. 故障现象

配置完两个server块并执行systemctl reload nginx(重新加载服务)后,进行测试:

curl-H"Host: mytest.com"http://127.0.0.1# 预期:欢迎页curlhttp://127.0.0.1# 预期:自定义兜底页

实际结果:两条命令均返回了 Nginx 原生的默认欢迎页,自定义兜底页未生效。

2. 排查思路与过程

面对“路由串台”,我采用了分层排查与控制变量法

  • 应用层验证
    执行nginx -t提示语法正常。但为了排除热加载(reload)未完全生效的极端情况,我执行了systemctl restart nginx(重启服务)强制重启,问题依旧。
  • 检查配置细节
    仔细核对兜底server块的root指令,发现路径被误写为:
    root /var/www/default/html;
  • 对比实际物理路径
    通过ls -ld /var/www/default检查,发现实际存在的目录是/var/www/default,并不存在html这个子目录。
  • 推导结论
    由于root路径指向了一个不存在的目录,Nginx 无法在该块中正确找到index.html。在复杂的虚拟主机匹配和隐式默认规则下,请求未能按预期返回自定义页面,而是落入了原生的默认欢迎页配置中。

3. 解决方案

修正root路径,去掉多余的/html

root /var/www/default;

执行nginx -t检查语法并systemctl reload nginx重载配置。
再次通过 IP 访问,此时 Nginx 成功匹配到了正确的物理目录,但页面并未正常显示,而是抛出了新的错误:403 Forbidden


三、 故障二:访问兜底页面报 403 Forbidden

1. 故障现象

解决路由问题后,通过 IP 访问兜底站点,curl返回403 Forbidden

2. 排查思路与过程

403 错误通常意味着“请求已到达服务器,但被拒绝访问”。我按照“文件系统权限 ➡️ 系统安全策略”的顺序进行排查:

  • 基础文件系统权限排查

    ls-ld/var/www/default# 目录权限 drwxr-xr-x (正常)ls-l/var/www/default/index.html# 文件权限 -rw-r--r-- (正常)

    权限配置完全符合 Nginx 运行用户(nginx)的读取要求,排除基础权限问题。

  • 系统安全层(SELinux)排查
    Rocky 9 默认开启 SELinux(Enforcing 模式),它会在基础权限之上进行强制访问控制(MAC)。

    1. 临时宽容测试:执行setenforce 0后,访问立刻恢复正常;执行setenforce 1恢复严格模式后,再次 403。确诊为 SELinux 拦截。
    2. 检查安全上下文标签
      执行ls -Zd /var/www/default,输出unconfined_u:object_r:default_t:s0 /var/www/default,发现该目录的标签为default_t。而 Nginx 进程(httpd_t)只被允许读取带有httpd_sys_content_t标签的 Web 目录。由于是我手动新建的目录,SELinux 没有自动为其分配正确的 Web 标签。

3. 解决方案(生产环境最佳实践)

很多新手会选择直接永久关闭 SELinux,但这在生产环境中是严重的安全违规。我采用了semanage工具进行永久且规范的上下文修复

  1. 安装 SELinux 策略管理工具:
    sudodnfinstallpolicycoreutils-python-utils-y
  2. 添加目录及其子文件的上下文规则:
    sudosemanage fcontext-a-thttpd_sys_content_t"/var/www/default(/.*)?"
  3. 刷新并应用规则:
    sudorestorecon-Rv/var/www/default
  4. 最终验证
    确保 SELinux 处于 Enforcing 状态(getenforce),再次访问,页面正常显示。故障二完美解决。

四、 复盘与避坑指南

1. 排查思维总结

  • 路由异常:不要只盯着自己写的配置,当出现“串台”或未按预期返回时,一定要仔细核对root物理路径是否真实存在,并排查include引入的“幽灵文件”(如conf.d/*.conf),确保default_server的全局唯一性。
  • 403 异常:建立条件反射。在 RHEL/CentOS/Rocky 系系统中,只要基础权限(rwx)没问题却报 403,第一嫌疑人永远是 SELinux

2. SELinux 修复规范

  • ❌ 错误做法setenforce 0(临时)或修改/etc/selinux/config为 disabled(永久关闭)。这会留下巨大的安全隐患。
  • ✅ 正确做法:使用semanage fcontext定义规则,配合restorecon刷新生效。这才是标准姿势。