Nginx防盗链需用valid_referers识别合法来源,配合if设标志变量,再通过internal location重定向返回403图片或HTML提示页;禁止直接if中return 403。

在 Nginx 中实现防盗链,并对盗链请求返回自定义的 403 图片或提示页,核心是通过 valid_referers 指令识别合法来源,再结合 if 和 rewrite 或 return 实现响应控制。注意:不能直接在 if 中使用 return 403 后输出图片(Nginx 不支持),需借助 error_page 机制或内部重定向。
配置合法 referer 并拦截非法请求
在 server 或 location 块中定义允许的来源,不匹配则设变量标记:
valid_referers none blocked server_names
*.example.com example.com
~\.google\.
~\.baidu\.;上述配置表示允许:无 referer(直接访问)、合法域名(含子域)、Google/Baidu 等搜索引擎爬虫。注意:blocked 匹配被防火墙或浏览器插件 stripped 的 referer(值非空但格式异常)。
接着用 if 判断并设置一个标志变量(如 $invalid_referer):
if ($invalid_referer) {
set $bad_ref "1";
}返回自定义 403 图片(推荐方式)
最稳妥的做法是:将盗链请求内部重定向到一个专用 location,该 location 返回指定图片(如 /403-forbidden.png),并统一返回 403 状态码:
location / {
valid_referers none blocked server_names *.example.com;
if ($invalid_referer) {
rewrite ^(.*)$ /403-forbidden.png break;
}
}
<p>location = /403-forbidden.png {
internal; # 仅允许内部 rewrite 访问,禁止外部直接请求
alias /usr/share/nginx/html/403-forbidden.png;
add_header Content-Type image/png;
return 403;
}-
internal是关键:防止别人猜到路径后直接访问这张图,绕过防盗链逻辑 -
alias指向真实图片路径(注意结尾不带斜杠,且路径需存在、Nginx 有读取权限) -
return 403确保响应状态码正确,浏览器和爬虫能识别为拒绝访问
返回纯文本或 HTML 提示页
若想返回文字提示(如“禁止盗链”),可类似处理:
location /images/ {
valid_referers none blocked server_names *.example.com;
if ($invalid_referer) {
rewrite ^(.*)$ /403.html break;
}
}
<p>location = /403.html {
internal;
alias /usr/share/nginx/html/403.html;
add_header Content-Type text/html;
return 403;
}确保 /usr/share/nginx/html/403.html 文件存在,内容可为简洁提示,例如:
<!DOCTYPE html> <html><body style="margin:0;font-family:sans-serif"> <h2 style="color:#e74c3c;text-align:center;margin-top:20vh">❌ 盗链禁止</h2> <p style="text-align:center;color:#7f8c8d">请通过正规渠道访问资源</p> </body></html>
注意事项与避坑点
-
if在 location 中使用是安全的,但在 server 级别慎用(可能引发意外行为) - 不要写
if ($invalid_referer) { return 403; }—— 这样无法返回图片,只能返回空白 403 响应体 - 测试时用 curl 模拟盗链:
curl -H "Referer: https://evil.com" https://your.site/image.jpg - CDN 或反向代理后,实际 referer 可能被覆盖,需确认
$http_referer是否为原始值(必要时检查X-Forwarded-For或调整 CDN 设置)


















