记一次 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)。- 临时宽容测试:执行
setenforce 0后,访问立刻恢复正常;执行setenforce 1恢复严格模式后,再次 403。确诊为 SELinux 拦截。 - 检查安全上下文标签:
执行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工具进行永久且规范的上下文修复:
- 安装 SELinux 策略管理工具:
sudodnfinstallpolicycoreutils-python-utils-y - 添加目录及其子文件的上下文规则:
sudosemanage fcontext-a-thttpd_sys_content_t"/var/www/default(/.*)?" - 刷新并应用规则:
sudorestorecon-Rv/var/www/default - 最终验证:
确保 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刷新生效。这才是标准姿势。