Nginx通过internal指令实现防盗链兜底保护:非法Referer请求内部重定向至受internal保护的提示图,该图路径需单独配置、禁用referer校验且不可外部直连,确保安全与体验兼顾。

在 Nginx 的 location 块中结合 internal 指令实现防盗链兜底保护,核心思路是:当非法 Referer 请求触发拦截时,不直接返回 403 或空白,而是内部重定向到一张“仅限内部访问”的提示图或占位图——这张图本身受 internal 保护,外部无法直连,从而兼顾用户体验与资源安全。
明确区分合法资源与兜底资源路径
避免把提示图和真实图片放在同一目录下。推荐做法:
- 真实图片走
/img/或正则匹配后缀(如location ~* \.(jpg|png|webp)$) - 兜底提示图单独存放,例如
/_assets/forbidden.jpg,且该路径必须配置internal - 确保兜底图所在 location 不匹配任何防盗链规则,否则会形成循环或拦截失败
配置合法资源 location 并触发内部跳转
在保护资源的 location 中,用 if ($invalid_referer) 判断后不返回错误码,改用 error_page 或 rewrite ... break 跳转到内部路径:
- 推荐方式(更可控):
error_page 403 =200 /_assets/forbidden.jpg;,再配合该路径的internal声明 - 替代方式:
rewrite ^(.*)$ /_assets/forbidden.jpg break;,但需确保 rewrite 后的路径已定义且启用 internal - 注意:不能用
return 302,那是外部重定向,会暴露兜底图地址,失去保护意义
为兜底图路径声明 internal 并关闭防盗链
兜底图路径必须显式声明为 internal,且禁用 Referer 校验,否则跳转会失败:
location = /_assets/forbidden.jpg { internal; alias /usr/share/nginx/html/_assets/forbidden.jpg; }- 不要在此 location 中写
valid_referers或if ($invalid_referer),否则内部跳转也会被拦 -
alias比root更适合单文件,避免路径拼接错误 - 可加
expires max;和add_header Cache-Control "public, immutable";提升复用效率
验证与常见避坑点
部署后需验证两个关键行为是否生效:
- 用
curl -e "https://evil.com" https://yoursite.com/img/test.jpg应返回兜底图内容(HTTP 状态码仍是 200),而非 403 - 直接请求
https://yoursite.com/_assets/forbidden.jpg必须返回 404 或 403,证明internal生效 - 若出现 500 错误,检查
alias路径是否存在、权限是否可读,以及是否遗漏分号 - 微信内嵌浏览器、某些 App 可能不带 Referer,建议白名单中保留
none blocked,避免误伤


















