Nginx网站403:目录、权限与访问规则排查

网站出现 403 Forbidden,先确认是谁拒绝了这次访问:Nginx、网站程序,还是前面的 CDN 或访问防护。错误页写着“nginx”,不能单凭这一点判断故障位置。

以下以 Linux 上的 Nginx 为例,命令在运行该实例的服务器 SSH 会话中执行,需要 sudo 权限。面板和容器部署应使用各自的程序、配置与日志路径;不要拿宿主机另一套 Nginx 的检查结果代替。

1. 用同一次请求对齐配置与日志

记下报错时间和时区、完整域名、URL 路径、访问者 IP,以及是否已登录网站。用浏览器重新打开一次原来的只读页面;直接访问服务器 IP 可能进入另一个站点,不能作为原域名的验证结果。不要为复现问题重复提交支付、删除等操作。

先查看 Nginx 进程及启动参数:

ps -C nginx -o user,pid,ppid,args

从 master process 行核对程序路径及启动时的 -c、-p 参数。下面仅示范程序位于 /usr/sbin/nginx、配置位于 /etc/nginx/nginx.conf 的安装方式;路径和额外参数要与当前实例一致。没有查到进程时,先确认服务器、容器和进程名称是否正确。

sudo /usr/sbin/nginx -T -c /etc/nginx/nginx.conf

-T 检查并打印当前磁盘上的配置,包含被引用的配置文件。它不会重载服务,也不证明运行进程已经加载了这些内容。根据域名、监听端口和匹配的 location,找到该站点的 access_log 与 error_log。配置输出可能含敏感信息,不要整份公开。

将下面的两个日志路径换成实际值,查看刚才请求对应的记录;日志查找方法见用 Nginx 日志定位网站访问问题。

sudo tail -n 100 /var/log/nginx/access.log
sudo tail -n 100 /var/log/nginx/error.log
同一次请求的证据 下一步
directory index of "…" is forbidden 检查实际目录、首页文件和 index,见第 2 步。
Permission denied,同时指出具体文件或目录 核对工作进程身份、逐级目录权限及安全策略,见第 3 步。
access forbidden by rule 核对访问规则与实际来源地址,见第 4 步。
已有访问日志中的 $upstream_status 记录为 403 上游返回了 403,继续查对应应用日志、登录状态和业务权限。
浏览器收到 403,但源站没有找到对应请求 先核对日志位置、时区、日志是否关闭或缓冲,以及 CDN/防护入口的记录,不能直接认定源站正常。

访问量大时,最后 100 行可能已不包含那次请求,应按记录的时间继续查找。error.log 没有新报错,也不能排除应用主动返回 403。

2. 目录索引被拒绝:先找真实首页

出现 directory index 时,先看日志里的目录是不是网站应该使用的目录。常见情况是首页没有上传、解压后多套了一层目录,或应用入口在 public 子目录,而站点仍指向项目根目录。

root 会把当前 URI 接在配置路径之后;alias 会按匹配的 location 替换路径。例如 location /images/ 配置 alias /srv/baoleyun-demo/assets/; 后,/images/logo.png 对应的是 /srv/baoleyun-demo/assets/logo.png,不能再拼一次 images。

在实际目录检查首页是否存在,以下路径需要替换:

sudo ls -la /srv/baoleyun-demo/public/

对照该位置的 index 列表,检查文件名和大小写。缺少文件就补回正确部署文件;目录指错就修正对应站点路径。PHP 网站还要核对原有 PHP 处理配置,不能只把首页名改成 index.php 就认为处理完成。

不要通过开启 autoindex 来掩盖问题,它会允许列出目录内容。备份目录或私有目录返回 403 可能正是预期结果,不应为了消除报错把它公开。

3. 文件权限被拒绝:检查整条路径

使用第 1 步中 worker process 行的用户判断权限,而不是使用主进程的 root 身份。把命令中的路径换成错误日志指出的实际文件:

sudo namei -l /srv/baoleyun-demo/public/index.html

输出会逐级显示路径、权限、属主和属组。Nginx 读取静态文件,既需要对文件有读取权限,也需要对途经的每一级目录有 x(搜索/穿过)权限。文件本身可读,但上一级私人目录不允许进入,仍会被拒绝;软链接还要检查其目标路径。

只修正已确认错误的目录或文件,并保留修改前的权限和归属记录。不要执行整站 chmod 777 或把所有文件改成 Nginx 用户所有。权限位和归属的操作见Linux 文件权限与归属教程;使用 ACL 的路径还要核对对应的 ACL。

普通权限看起来正确时,再检查实际启用的安全模块。使用 SELinux 的系统可查看模式和最近的拒绝记录:

getenforce
sudo ls -Zd /srv/baoleyun-demo/public /srv/baoleyun-demo/public/index.html
sudo ausearch -m AVC,USER_AVC -ts recent -i

recent 查询最近约 10 分钟。核对拒绝时间、进程和路径是否与本次请求一致,并区分强制模式与只记录的宽容模式;不要把其他进程的拒绝日志当作原因。路径仍需替换,工具未安装也不代表不存在安全策略。

使用 AppArmor 的系统,可查看加载的配置及近期内核日志:

sudo aa-status
sudo journalctl -k --since "10 minutes ago" --no-pager

查找与当前请求相符的 apparmor="DENIED"、进程和目标路径。没有日志不等于没有限制。将证据交给维护人员修正对应路径标签或必要的访问规则,不要关闭 SELinux/AppArmor 来恢复网站。

4. 访问规则或应用返回 403

发现 access forbidden by rule,就在匹配到的配置位置查 allow、deny 等限制。地址规则按顺序匹配,不能只看到一条 allow 就认为已放行。网站经过反向代理时,Nginx 看到的来源地址还可能是代理地址,应以日志和当前可信代理配置为准。

先确认被拒绝的资源是否应该公开,再调整具体规则。不要删除全部 deny、后台访问限制或防护规则。若证据指向应用返回的 403,应检查应用的账号权限、会话、请求方法或防跨站请求校验;修改站点目录权限通常解决不了这些问题。

5. 修改后验证原来的页面

只改一处已定位的问题。需要修改 Nginx 配置时,先备份对应配置文件;修改后,用同一程序、同一配置与启动前缀执行 -t 检查。以上面的标准安装为例:

sudo /usr/sbin/nginx -t -c /etc/nginx/nginx.conf

只有检查成功,才使用该实例原有的管理方式重载,并检查重载是否成功;面板、系统服务和容器不能混用管理入口。配置检查成功不等于网页已经恢复。

回到最初的域名、路径和登录状态再次访问,确认页面内容正确、相关图片或接口正常,并核对这次访问的状态及日志。若原本应受限的资源也被公开,立即恢复本次修改。故障变成 502/504 时,转查Nginx 上游与 PHP-FPM,不要继续放宽文件权限。

仍无法定位时,提供报错时间与时区、URL 路径、对应日志片段、实际站点目录和最近一次变更;按日志脱敏指南处理后提交工单。

技术依据:Nginx 官方模块与命令行文档,Linux 路径解析和 namei 手册,SELinux 与 AppArmor 官方排查文档。核对日期:2026 年 11 月 4 日。