nginx防盗链核心是通过valid_referers校验referer头,合法来源放行,非法来源返回403或重定向;需结合limit_conn、limit_rate等四层防护,并压测验证高并发下拦截稳定性与资源占用。

直接压测防盗链规则本身没有意义——真正要测的是:当大量盗链请求涌来时,Nginx 是否仍能稳定拦截、不丢连接、不拖慢合法请求,且自身资源(CPU、内存、worker 连接数)不被耗尽。重点不是“能不能拦”,而是“拦得住多少、拦得有多稳”。测试必须绕过浏览器 Referer 伪造的表层,直击真实攻击模式。
用真实攻击模型构造压测流量
别只用 curl -H "Referer: http://evil.com" 循环发请求。这种单线程、低并发、无连接复用的写法完全模拟不了真实盗链工具(如 aria2、IDM、Python 多线程脚本)的行为。应按以下方式构造:
- 用 ab、wrk 或 hey 启动 50–200 并发,每秒持续发起带非法 Referer 的 GET 请求(如
wrk -t10 -c200 -d60s --latency "http://yoursite.com/img/logo.png"),并在请求头中固定设置-H "Referer: http://badsite.net" - 加入 多 IP 源模拟:用 socat 或 nginx 自身做简单代理层,让请求看起来来自不同客户端 IP(避免被 limit_conn 早期卡死,从而测出 referer 判断阶段的真实吞吐)
- 混入 合法 Referer 流量(如
-H "Referer: https://yoursite.com/page"),观察正常用户是否被误伤或延迟升高
监控四项核心指标,而非仅看返回码
不能只盯着 403 数量。需在压测同时实时采集:
- nginx worker 进程 CPU 使用率:若单 worker 超过 85%,说明 referer 解析或 map 查表已成瓶颈(尤其 valid_referers 配了过多正则时)
- active connections 数与 waiting 状态连接数:watch -n1 'ss -s | grep -E "(established|waiting)"';waiting 持续 > 200 表示事件循环被阻塞,可能因 send_timeout 或 keepalive_timeout 设置不当
- error.log 中 limit_conn_rejected / invalid_referer 日志频次:确认拦截动作是否真正在起效,而非因配置错位(如 location 未生效)而漏过
- upstream 响应时间 P95(如有 proxy_pass):确保防盗链逻辑未意外触发后端转发(常见于 try_files fallback 或 root 继承错误)
验证四层防护是否全部咬合生效
单靠 valid_referers + if 是裸奔。极限并发下必须验证你配齐的四层机制是否逐级拦截:
-
来源识别层:检查 $invalid_referer 变量是否对非法请求稳定为 1(可在 log_format 中加
$invalid_referer字段验证) -
连接压制层:用
limit_conn_zone $binary_remote_addr zone=dl_conn:10m+limit_conn dl_conn 2,压测时观察是否在第 3 个并发连接即返回 503,且 error.log 出现limiting connections by zone "dl_conn" -
速率控制层:开启
limit_rate $limit_rate_value后,用 iftop 或 ss -i 观察实际输出速率是否被压至设定值(如 40k),而非全速跑满 -
路径隔离层:确认 location 使用的是
^~ /download/而非~ \.zip$;用nginx -T | grep -A5 "location ^~ /download/"验证该块未被其他正则 location 覆盖
对比有无防盗链时的磁盘 I/O 与响应延迟
最终目标是保带宽、护磁盘。在压测前后执行:
-
iostat -x 1 5:关注 %util 和 await;盗链拦截生效时,%util 应明显低于未启用状态(尤其使用 SSD 时) -
curl -o /dev/null -s -w "%{time_starttransfer}\n" http://yoursite.com/img/logo.png(合法 Referer):记录首字节延迟,确保防盗链未拖慢正常访问 - 若返回提示图(如 /images/hotlinking.png),确认该路径 location 单独配置了
valid_referers none blocked *.yourdomain.com;,避免二次触发防盗链形成死循环











