排查 Nginx 403 Forbidden,从宝塔错误日志分清目录索引、路径权限、访问规则与 CDN 拒绝,安全恢复站点并保留敏感目录保护。
先看错误日志,不要先把整个网站目录改成 777:Nginx 返回 403 Forbidden,说明请求已经到达 Web 服务,但当前请求被拒绝。使用宝塔面板时,先进入“网站 → 目标站点 → 日志”,查看同一时间的错误日志;也可以通过 SSH 查看站点配置中声明的 error_log。日志若出现 directory index ... is forbidden,优先检查首页文件和 index;出现 Permission denied,检查路径每一级目录的执行权限与文件读取权限;出现 access forbidden by rule,检查 deny、IP 白名单和匹配到的 location。
读取配置、日志和权限通常不额外收费。修改权限或 Nginx 配置一般也不会直接删除网站数据,但批量 chown、chmod -R 可能让上传目录、密钥和配置文件暴露,错误的重载会让整站中断。动手前保存站点配置副本,记录原属主和权限;修复单个证据明确的问题,不对整个 /www/wwwroot 做无差别修改。
先确认 403 来自哪一层
浏览器显示 403,不一定就是源站 Nginx。CDN、WAF、宝塔安全插件、应用框架和对象存储都能返回同一状态码。先用源站本机请求与公网请求对比,把域名和源站监听端口替换为实际值。若站点只允许特定 Host,请保留 Host 请求头。
curl -I https://你的域名/
curl -I -H 'Host: 你的域名' http://127.0.0.1:源站端口/
sudo nginx -T | less
公网 403、源站本机 200,优先查 CDN/WAF 规则、访问频率、地区限制和回源 Host;两边都 403,继续查 Nginx 与文件系统。nginx -T 会输出完整生效配置,可能包含域名、路径和上游地址,不要把未经脱敏的结果公开。宝塔页面里看到的配置只有在语法检查和重载成功后才会生效,因此必须以 nginx -T 为准。
根据错误日志选择处理分支
| 日志或现象 | 通常意味着什么 | 默认检查 |
|---|---|---|
directory index of ... is forbidden | 请求落到目录,但没有匹配的首页文件,目录列表又未开启 | 核对真实 root、index 和部署产物 |
open() ... failed (13: Permission denied) | Nginx 工作用户不能穿过父目录或读取目标文件 | 逐级看路径权限、属主、ACL 与安全模块 |
access forbidden by rule | 生效配置中的访问控制规则主动拒绝 | 检查匹配的 location、allow、deny 和 include 文件 |
| 源站 200,经过 CDN 后 403 | 拒绝发生在 CDN、WAF 或回源身份层 | 查边缘事件、规则命中和回源请求差异 |
| 只有管理后台或单个路径 403 | 更像路径级规则、应用权限或安全插件 | 不要改全站权限,先定位该 URI 的配置和应用日志 |
出现 directory index forbidden 时怎么处理
Nginx 官方说明,index 模块处理以斜杠结尾的目录请求,并按配置顺序查找首页文件。多数网站不应该为了消除 403 就开启目录列表;默认做法是确认部署产物确实包含首页文件,并让 root 指向正确目录。
在宝塔进入“网站 → 目标站点 → 设置 → 配置文件”,记录 server_name、root 和 index。PHP 站常见首页是 index.php,静态站可能是 index.html,某些前端构建产物位于 dist 或 public 子目录。不要凭项目根目录名称猜路径。
server {
server_name example.com;
root /www/wwwroot/example.com/public;
index index.php index.html;
}
上面只是结构示例,域名和目录必须替换。Nginx 的 root 会把请求 URI 拼到配置路径后面;若项目实际入口位于另一目录,首页文件存在也可能找不到。确认后先运行 sudo nginx -t,只有语法通过才执行重载。若构建目录缺失,应重新完成部署或恢复上一个已验证产物,而不是创建空的 index.html 掩盖发布失败。
出现 Permission denied 时逐级检查权限
Nginx 读取文件不只需要目标文件可读,还要能“穿过”路径上的每一级父目录。先确定工作进程用户,再逐级查看路径。宝塔常见用户可能是 www,其他发行版可能是 nginx 或 www-data,不能写死。
ps -eo user,group,comm | grep '[n]ginx'
namei -l /www/wwwroot/example.com/public/index.html
getfacl -p /www/wwwroot/example.com/public/index.html
sudo -u 实际Nginx用户 test -r /www/wwwroot/example.com/public/index.html && echo readable
sudo -u 实际Nginx用户 test -x /www/wwwroot/example.com/public && echo searchable
把路径和用户替换为现场值。若 namei -l 显示某一级目录没有执行权限,应只修复那一级的最小必要权限;若 ACL 明确拒绝,则先确认它是否属于既有安全策略。普通公开静态文件常见权限并不等于所有项目都应统一为 644/755,上传目录、缓存目录、私钥和环境文件有不同边界。禁止直接执行 chmod -R 777,也不要在不清楚应用写入用户时对全站递归改属主。
若项目放在 /root、个人家目录或挂载盘,即使文件本身可读,父目录、NFS 挂载选项、容器卷映射或安全模块也可能阻止访问。此时优先把公开产物部署到为 Web 服务设计的目录,并只授予所需读取权限,不为方便而放宽整个家目录。
出现 access forbidden by rule 时检查真实匹配配置
Nginx 的 allow 和 deny 会按顺序检查,命中第一条规则后停止。规则还可能藏在宝塔生成的 include 文件、伪静态、安全插件或单独的路径配置中。先从完整配置找到域名对应的 server,再检查请求 URI 最终匹配哪个 location。
sudo nginx -T 2>&1 | grep -nE 'server_name|location|allow|deny|return 403|auth_basic'
curl -sS -o /dev/null -D - -H 'Host: 你的域名' http://127.0.0.1:源站端口/出错路径
不要看到 deny all 就立即删除。限制隐藏文件、备份、配置目录或管理入口的规则通常是正确的。若只是办公室出口 IP 变化,应更新明确的受控地址并保留默认拒绝;不要为了临时恢复后台,把管理路径开放给所有公网来源。修改前保存规则顺序,重载后从允许和不允许的来源分别验证。
配置和权限都正常时还要查什么
在启用 SELinux 的系统上,Unix 权限正确不代表安全上下文允许 Nginx 读取;先用 getenforce 和审计日志确认,不要直接永久关闭 SELinux。在使用 AppArmor、容器或只读挂载的环境中,也要核对配置文件、卷挂载和访问策略。安全模块没有明确拒绝证据时,不要为了排障先关闭它。
如果 Nginx 日志显示请求已交给 PHP 或上游应用,而应用自己返回 403,应查看 PHP、框架、WordPress 安全插件或应用鉴权日志。此时调整 Nginx 文件权限通常无效。WordPress 更新后故障可参考WordPress 维护模式恢复;PHP-FPM 无法处理请求时参考宝塔 PHP 502 排查。
修复后怎样验证和回退
- 执行
nginx -t,确认语法和引用文件都能读取。 - 用源站本机请求验证首页、一个静态资源和原来出错的具体路径。
- 再从公网验证 HTTP 状态、页面内容、登录入口和低风险动态请求。
- 检查错误日志不再出现同一拒绝原因,同时确认隐藏文件、备份目录和管理路径仍被保护。
- 若有 CDN,清理对应 URL 缓存或等待缓存失效后复查,不做全站无差别清缓存。
修改后出现新的 404、500 或敏感文件可访问,应立即恢复保存的站点配置和原权限,运行语法检查后重载。若只改了单个目录权限,就回退该目录,不执行全盘反向修改。Nginx 反向代理与 HTTPS 的基础配置可参考Nginx 反向代理教程;权限含义与 ACL 可继续查看Linux 文件权限教程。
官方资料
以上资料于 2026 年 9 月 6 日核验。宝塔版本、Nginx 编译参数、Linux 发行版和项目目录结构可能不同;最终以当前主机的完整生效配置、错误日志与逐级权限检查为准。

