应使用 error_page 403 =200 /img/forbidden.png 实现盗链提示图,配合 valid_referers none blocked 白名单及独立 location 配置,避免循环和参数丢失。

想让盗链请求返回一张默认提示图(比如“禁止盗链”的小图),关键不是简单 rewrite,而是用 error_page + 403 拦截 + 内部重定向 的组合,既保持语义正确,又避免循环和参数丢失。
必须先定义 Referer 白名单
valid_referers 必须写在匹配资源的 location 块里,不能放在 http 或 server 顶层。漏掉 none 和 blocked 会导致大量合法访问失败:
- none:允许直接在浏览器地址栏输入图片 URL、书签访问、PWA 离线加载等无 Referer 场景
- blocked:允许被隐私插件(如 uBlock)、企业网关、本地调试(localhost)清空或篡改 Referer 的请求
示例(只对图片生效):
location ~* \.(jpg|jpeg|png|gif|webp)$ {
valid_referers none blocked example.com *.example.com;
if ($invalid_referer) {
return 403;
}
expires 7d;
}
用 error_page 替代 if + rewrite
不要用 if ($invalid_referer) { rewrite ^/ /img/forbidden.png break; } —— 它会丢弃原始查询参数(如 ?v=2),导致提示图 404;状态码还是 200,日志无法区分真实盗链。
推荐做法:触发 403 后,用 error_page 统一映射到提示图,且把响应码改成 200(可选):
error_page 403 =200 /img/forbidden.png;
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
这样语义清晰(拦截动作由 return 403 完成),响应内容由 error_page 托管,不干扰主逻辑。
为提示图单独配置 location 并关闭防盗链
如果提示图路径是 /img/forbidden.png,它自己也得能被正常访问,否则会陷入循环或 403。必须加一个精确匹配的 location:
location = /img/forbidden.png {
# 不写 valid_referers,不套 if 判断
# 可加缓存提升性能
expires max;
add_header Cache-Control "public";
}
这个 location 一定要放在主图片 location 之后(Nginx 按顺序匹配),确保优先命中精确路径,避免被前面的正则规则再次拦截。
验证是否生效
用 curl 模拟不同来源测试:
-
curl -H "Referer: https://bad-site.com" https://yoursite.com/test.jpg→ 应返回提示图内容,状态码 200(或 403,取决于 error_page 是否带 =200) -
curl -H "Referer: https://example.com" https://yoursite.com/test.jpg→ 应返回原图 -
curl https://yoursite.com/test.jpg(无 Referer)→ 应返回原图(因含 none)
检查 Nginx error log,若出现 rewrite or internal redirection cycle,说明提示图 location 没隔离好。

















