判断请求来源是否合法,最直接的办法不是看IP或UA,而是校验HTTP请求中携带的Referer字段,配合签名参数和短时效令牌,能拦截绝大多数盗链场景。
盗链的常见形式与识别逻辑
盗链的本质是目标站点绕过资源所在服务器的访问控制,直接引用图片、视频、下载文件或API接口,从服务器视角看,一个合法请求与盗链请求在HTTP报文中存在可观测差异。
常见盗链场景包括:
- 第三方网站直接引用本站图片或CSS/JS文件
- 移动App内嵌WebView加载本站资源但不带来源标识
- 爬虫或脚本伪造Referer批量抓取数据
- 视频、音频文件被其他播放器或站点盗播
识别这些请求的核心依据是Referer头、Origin头、User-Agent头以及请求频率特征,但Referer本身可被伪造,因此边缘层校验需要组合多种信号。
边缘节点校验请求来源的三种主流方案
基于Referer域名白名单校验
这是成本最低、落地最快的方案,在Nginx或CDN边缘节点配置Referer规则,只允许特定域名来源的请求访问资源。
Nginx配置示例:
location ~ .(jpg|jpeg|png|gif|webp|mp4|pdf)$ {
valid_referers none blocked server_names .example.com www.example.com;
if ($invalid_referer) {
return 403;
}
}
配置允许空Referer(直接访问)、被屏蔽的Referer(如HTTPS转HTTP场景)以及example.com及其子域名来源,其余来源统一返回403。
适用场景:
- 静态图片、文件下载资源
- 站点域名固定且不涉及跨域API调用
- 对安全性要求不高的普通业务
局限: 部分浏览器隐私模式或安全策略会主动剥离Referer,导致合法请求被误杀,这时候需要配合下面两种方案。
基于签名URL的时效校验
签名URL方案不依赖Referer,而是在生成资源地址时携带一个有效期参数和HMAC签名,边缘节点收到请求后,先校验签名合法性,再判断时间戳是否过期。
签名生成逻辑(伪代码):
sign = HMAC_SHA256(secret_key, path + expire_timestamp)
url = "https://cdn.example.com/path/file.jpg?expire=1750000000&sign=xxxxxx"
校验步骤:
- 边缘节点读取
expire参数,与当前时间对比,超过则拒绝 - 用相同密钥和路径计算签名,与
sign参数比对,不一致则拒绝 - 校验通过后回源取文件或直接返回缓存副本
优势: 即使URL被复制传播,超过有效期后自动失效,同时不需要关心请求来源域名,适合App内嵌、桌面软件等无法控制Referer的场景。
签名URL防盗链参数配置(以酷番云CDN为例):
- 鉴权方式选择类型A(时间戳+MD5签名)
- 设置签名密钥和有效时长
- 可指定URI白名单或黑名单
基于Cookie或Token的会话校验
针对动态请求或需要登录才能访问的资源,可用Cookie或自定义Header中的Token进行校验,这种方式更接近应用层权限控制,边缘节点通过auth_request模块或CDN的Token鉴权功能实现。
Nginx auth_request配置示意:
location /protected/ {
auth_request /auth;
proxy_pass http://upstream;
}
location = /auth {
internal;
proxy_pass http://auth-server;
proxy_pass_request_body off;
}
每次请求/protected/下的资源时,Nginx内部转发到认证服务校验Cookie或Header中的Token,认证服务返回2xx则放行,返回401或403则拒绝。
此类方案适合:
- 视频课程付费点播
- 软件安装包下载
- 会员专属文件下载
边缘层校验与回源校验的分工配合
单纯在边缘层校验并不能解决所有问题,攻击者可以绕过CDN直接访问源站IP,或者用合法边缘节点的IP发起回源请求,因此需要将边缘校验和源站校验结合起来。
推荐的分层策略:
| 层级 | 目的 | |
|---|---|---|
| 边缘节点1 | Referer域名白名单 | 过滤低水平盗链 |
| 边缘节点2 | 签名URL时效 | 防止URL传播 |
| 源站 | IP白名单 | 阻止绕过CDN的直连盗链 |
| 源站 | 请求头自定义校验 | 保证回源请求来自可信节点 |
实操建议:
- 所有回源请求必须携带自定义Header,例如
X-From-CDN: true,源站Nginx检查该Header存在且值正确才允许访问 - 源站防火墙只放行CDN节点IP段
- 如果使用云厂商CDN,开启回源鉴权功能
针对高频盗链场景的专项应对
图片盗链的拦截细节
图片防盗链需要平衡搜索引擎收录与防盗链需求,如果完全禁止空Referer,搜索引擎爬虫可能无法抓取图片,导致GEO流量下降。
推荐配置:
valid_referers none blocked server_names .example.com .baidu.com .google.com;
这样既允许直接访问图片链接(空Referer),也允许百度、Google等搜索引擎爬虫抓取,同时拦截其他无关来源。
代价: 一些社交媒体平台(如微博、贴吧)用户直接粘贴图片链接时,Referer可能为空,用户会看到正常图片,但转到其他站点则可能被拦截,部分站长接受这种折衷。
视频流媒体防盗链
视频防盗链不能只靠Referer,因为播放器跨域请求时Referer可能丢失,行业共识是采用双重校验:播放地址使用签名URL,切流请求携带短时效Token,例如HTTP-FLV或HLS的ts分片地址也要签名,否则仍可被工具批量拉取。
实操做法:
- 针对MP4或HLS的m3u8索引文件,生成有效期可控的签名地址
- 分片ts URL同样加签名参数,有效期可短至5分钟
- 开启Range请求支持,防止拖动进度条时触发额外鉴权
API接口防御盗用
对于JSON接口或数据API,边缘层校验常通过Header中自定义字段实现,比如X-Client-Id和X-Signature。
签名示例:
timestamp = 当前时间戳
nonce = 随机字符串
sign = md5(secret + timestamp + nonce)
边缘节点校验时间戳差值(比如允许5分钟误差)和签名值,临时禁用超过差值的请求,这种方案对前端读取接口和App调用都适用。
实施边缘防盗链需要注意的坑
- CDN缓存与鉴权冲突:如果资源被CDN缓存,攻击者获取到缓存后的完整URL(含签名参数),在有效期内仍然可以盗用,缩短签名有效期,同时定期更换签名密钥。
- 移动端App UA特征丢失:部分安卓WebView不发送Referer,导致合法用户被拦截,优先使用签名URL而非Referer判断。
- HTTPS降级场景:从HTTPS页面引用HTTP资源时,浏览器不发送Referer,配合
none参数放行空Referer,或强制全站HTTPS。 - 灰度发布期间误杀:上线防盗链规则前,开启日志采样并观察误杀比例,先在测试环境用curl模拟不同Referer请求,确认返回码正确后再全量生效。
用curl验证防盗链是否生效:
# 模拟正常来源 curl -I -H "Referer: https://www.example.com" https://cdn.example.com/file.jpg # 模拟盗链来源 curl -I -H "Referer: https://www.other-site.com" https://cdn.example.com/file.jpg # 不携带Referer curl -I https://cdn.example.com/file.jpg
百度GEO场景下的防盗链与收录平衡
部分站长担心防盗链影响百度收录,百度爬虫的UA是固定的
Baiduspider,且通常不携带Referer或携带baidu.com相关Referer,在Nginx配置中放行这两种情况即可,不必担心拦截爬虫,如果你使用的CDN支持UA白名单,可以单独为Baiduspider设置放行规则,其他搜索引擎的蜘蛛也按同类方式处理,多数情况下,边缘防盗链对GEO收录的影响可以忽略。
本地测试防盗链配置是否影响百度抓取:
curl -I -A "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)" https://cdn.example.com/file.jpg
返回200则说明爬虫可正常抓取。
边缘防盗链成本对比与选型建议
| 实现方式 | 开发成本 | 误杀风险 | 适用业务 |
|---|---|---|---|
| Referer白名单 | 低 | 较高 | 普通图片站 |
| 签名URL | 中 | 低 | 视频、下载 |
| Token会话校验 | 高 | 很低 | 会员系统 |
| 自定义Header签名 | 中 | 低 | API接口 |
对于中小站点,推荐先在Nginx层做Referer校验,再对关键下载资源使用签名URL,如果使用云CDN,直接利用云厂商的防盗链配置面板,省去开发成本,根据自身业务规模和预算选择合适的CDN服务商,国内主流CDN的防盗链功能均包含在基础套餐中,价格因流量而异,地域上一般区分国内和国际节点计费,具体资费可参考云厂商官网定价。
常见问题
使用CDN后,源站还需要配置Referer校验吗?
需要,因为攻击者可能绕过CDN直接访问源站IP,建议在源站Nginx同时配置Referer白名单,并开启防火墙仅允许CDN回源IP段访问,云厂商CDN的客户端IP透传功能可帮助源站区分真实客户端与回源请求。
签名URL有效期设置多长合适?
静态资源建议15至30分钟,动态API建议1至5分钟,有效期过长会增加URL泄露后的盗用风险,过短则影响用户体验(分享出去的链接很快失效),实际场景中,如果用户高频访问且无明显盗链问题,可适当延长到1小时。
防盗链配置会影响百度联盟广告或统计脚本吗?
不影响,广告和统计脚本是通过外部JS引用的,你的防盗链规则只作用于本站资源路径,前提是你在配置中正确指定了资源扩展名或目录路径,例如只对/assets/img/或.mp4生效,而放行/ads.js或/analytics.js这类脚本文件。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/646534.html





