防盗链本身不会直接导致重定向死循环,但与 rewrite、return 或 referer 检查逻辑错误组合使用时,可能因跳转目标被再次拦截而形成闭环,引发 err_too_many_redirects。

防盗链本身不会直接导致重定向死循环,但当它与 rewrite、return 或 referer 检查逻辑错误组合使用时,就可能触发 ERR_TOO_MANY_REDIRECTS,进而让浏览器卡死或白屏。关键不是“防盗链配置错了”,而是“防盗链判断后跳转的目标又被防盗链规则再次拦截”,形成闭环。
检查 referer 判断 + return/rewrite 是否构成闭环
常见错误写法是:对非白名单 referer 返回 302 跳转到一个提示页(如 /forbidden.html),而该提示页又落在同一 location 下,被再次检查 referer ——若提示页本身没有 referer(比如用户直接访问或从书签打开),就会再次触发跳转,反复执行。
- 确认跳转目标是否受相同防盗链规则约束:比如 location ~* \.(jpg|png|gif)$ { valid_referers none blocked server_names *.example.com; if ($invalid_referer) { return 302 /blocked.png; } },而 /blocked.png 本身也是图片,会再次进入这个块
- 解决办法:把提示资源(如 /blocked.png)移出受保护 location,或用独立 location 显式放行:location = /blocked.png { add_header X-Protected "no"; }
- 避免在正则 location 中嵌套 referer 判断+跳转,优先改用 error_page + named location 方式处理
验证 rewrite 与防盗链指令的执行顺序冲突
rewrite 在 location 内部先于 valid_referers 执行;如果 rewrite 改写了 URI,却未更新 $request_uri 或 $uri,可能导致 valid_referers 检查对象错位。例如 rewrite ^/img/(.*)$ /raw/ break; 后,$uri 变为 /raw/xxx,但 referer 检查仍按原始路径逻辑走,后续又跳转回 /img/,就可能套娃。
- 用 curl -I -e "https://bad.com" https://yoursite.com/img/test.jpg 观察 Location 响应头是否在两个地址间来回跳
- 在 location 块开头加 log_format custom '$remote_addr - $request_uri → $uri → $invalid_referer'; 配合 access_log 查看每次请求的实际匹配路径和 referer 判定结果
- 禁用 rewrite 或临时改用 last 标志,观察循环是否消失,可快速定位是否为 rewrite 干扰所致
排查防盗链跳转与 HTTPS 强制跳转叠加
当防盗链返回 302 到 http://yoursite.com/blocked.html,而 Nginx 同时配置了 HTTP→HTTPS 全局跳转,浏览器就会在 http 和 https 之间反复横跳。尤其在 CDN(如 Cloudflare)开启“Always Use HTTPS”时,更易放大该问题。
- 确保所有防盗链跳转目标都使用协议相对或全 HTTPS 地址:return 302 https://$host/blocked.html;
- 不要依赖 $scheme 在防盗链跳转中自动适配——若请求经多层代理,$scheme 可能失真;建议显式写 https://
- 检查 CDN 设置:关闭“Automatic HTTPS Rewrites”或“Always Use HTTPS”,先排除外部干扰再聚焦 Nginx 本身
用最小化复现隔离问题
新建一个干净的 server 块,只保留防盗链核心逻辑,用固定 referer 测试:
- 配置仅针对 .jpg 的简单规则,跳转目标设为 /ok.html(静态 HTML,无防盗链)
- 用 curl -I -e "https://google.com" https://localhost/test.jpg 看是否跳转一次即止
- 逐步加入 rewrite、proxy_pass、HTTPS redirect 等模块,每加一项就测试一次,定位触发点











