Nginx可通过valid_referers+if+log_format组合实现盗链请求单独记录:先用valid_referers识别非法referer并设$bad_referer变量,再在log_format中包含该变量,最后用access_log if=$bad_referer条件写入指定日志文件。

Nginx 防盗链本身不直接记录“盗链日志”,但可以通过 valid_referers + if + log_format 组合,把盗链请求单独标记并写入特定日志文件。
关键思路是:识别非法 referer 后,设置一个自定义变量(如 $bad_referer),再在 log_format 中引用它,配合 access_log 的条件写入,实现盗链行为的独立记录。
1. 定义合法来源和标记盗链请求
在 server 或 location 块中使用 valid_referers 判断 referer 是否合法,并用 if 设置标志变量:
valid_referers none blocked server_names *.example.com example.com;
if ($invalid_referer) {
set $bad_referer "1";
}说明:
-
none:允许空 referer(比如直接输入 URL 访问) -
blocked:允许被防火墙或代理 stripped 的 referer(含 http:// 或 https:// 但无法解析的) -
server_names:允许本域名及子域名 -
$invalid_referer是 Nginx 内置变量,匹配失败时为 1
注意:
if在location中可用,但不能放在server级顶层(除非在location内),否则可能失效或报错。
2. 自定义日志格式,包含盗链标识
在 http 块中定义一个带 $bad_referer 的日志格式:
log_format bad_referer '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$bad_referer';这个格式会在每行末尾输出 1(盗链)或空(正常)。
3. 配置条件日志输出(只记录盗链)
在 server 或 location 块中,用 access_log 的 if= 参数控制:
access_log /var/log/nginx/bad-referer.log bad_referer if=$bad_referer;
说明:
- 只有
$bad_referer为非空(即"1")时,才写入该日志 - 日志路径需确保 Nginx 进程有写权限(如
/var/log/nginx/目录可写)
4. 可选:返回 403 并记录(更严格防盗链)
如果还想拒绝盗链请求,加一行:
if ($invalid_referer) {
set $bad_referer "1";
return 403;
}这样既记录日志,又阻止访问。注意 return 会中断后续处理,所以 access_log 仍能记录(因为 return 发生在日志写入之后)。
不复杂但容易忽略的是变量作用域和 if 使用位置。只要 set 和 access_log if= 配合得当,就能干净分离盗链日志。


















