可通过nginx的$http_referer变量结合自定义日志格式、map指令和valid_referers指令,精准记录来源、分类流量类型、识别并拦截盗链请求,同时避免误拦与无效referer干扰。

可以通过 Nginx 的 $http_referer 变量记录请求来源,并结合日志格式与条件判断,清晰区分正常引荐流量和被防盗链规则拦截的请求。
在 access_log 中记录 referer 和拦截状态
Nginx 默认不记录 referer,需自定义日志格式。添加 $http_referer 和一个标记变量(如 $blocked)可同时看到来源和是否被拦截:
示例配置:
log_format referer_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$blocked"';
再定义一个变量用于标识防盗链拦截行为:
set $blocked "-";
if ($http_referer !~ ^https?://(www\.)?yourdomain\.com) {
set $blocked "blocked";
}
这样被拦截的请求在日志中会显示 "blocked",而正常请求为 "-",便于用 grep 或日志分析工具筛选。
用 map 指令更高效地分类 referer 来源
相比 if,map 更轻量、更安全,适合做 referer 分类或标记:
map $http_referer $referer_type {
default "other";
"~*yourdomain\.com" "internal";
"~*baidu\.com" "baidu";
"~*google\.com" "google";
"~*^$" "direct";
}
然后在 log_format 中加入 $referer_type,就能在日志里直接看到流量归属类型,比如 "baidu" 或 "direct",方便后续统计各渠道访问量。
识别并排除无效 referer 干扰
空 referer(如直接输入网址、HTTPS 页面跳转到 HTTP)、伪造 referer、浏览器隐私模式等会导致 $http_referer 不可靠。建议:
- 将空 referer(
$http_referer = "")单独归类为direct,但不视为“盗链” - 避免仅靠 referer 做关键权限控制,它可被客户端随意修改
- 对静态资源(如图片、JS、CSS)启用防盗链时,配合
valid_referers指令更规范:
location ~* \.(jpg|jpeg|png|gif|js|css)$ {
valid_referers none blocked server_names *.yourdomain.com;
if ($invalid_referer) {
return 403;
# 或重定向到默认图:rewrite ^/.*\.(jpg|png|gif)$ /placeholder.png break;
}
}
此时配合日志中的 $invalid_referer 变量(值为 "1" 或 ""),可精准统计拦截次数。
用日志分析快速定位异常或高频盗链
部署后,通过简单命令即可排查问题:
- 查看被拦截最多的外部域名:
awk '$12=="blocked" {print $11}' access.log | sort | uniq -c | sort -nr | head -10 - 统计各 referer 类型占比:
awk '{print $12}' access.log | sort | uniq -c | sort -nr - 检查是否误拦内部请求:
grep "blocked" access.log | grep "yourdomain.com"
注意:确保 Nginx 编译时启用了 --with-http_realip_module(如使用 CDN),否则 $remote_addr 可能是代理 IP,影响来源判断。











