4.3 防盗链:Referer 与签名
场景:一觉醒来流量费翻倍
某天早晨,监控显示 CDN 流量是平时的六倍。查日志,某论坛把我们的公开素材直接嵌入他们网页,图片全是我们的链接。他们出内容我们出钱,流量费实打实翻倍。那天下班前我们就上了 Referer 校验,评论区的盗链当天消失。
防盗链不是要不要做的问题,是什么时候做的问题。只要内容公开访问,就会被白嫖,区别只在早晚。
方案:三层防护
防盗链手段按强度与成本分层:
| 方案 | 强度 | 成本 | 适用 |
|---|---|---|---|
| Referer 黑白名单 | 低 | 零 | 基础防护 |
| IP 限频与 UA 检查 | 中 | 低 | 拦脚本 |
| URL 签名鉴权 | 高 | 中 | 核心资源 |
我们的策略是组合使用:公开素材用 Referer 白名单,核心资源走签名鉴权,脚本流量再叠频率限制。单层防盗链都有破解办法,组合起来抬高成本,攻击者自然换一家。
配置:CDN 鉴权参数
签名鉴权的配置在 CDN 域名设置里开启,Go 侧生成鉴权 URL:
// CDN 鉴权 URL:带过期时间与签名
url := cdn.AuthURL(rawURL, secret, time.Now().Add(15*time.Minute))
// 客户端每次访问都要带上 url 中的鉴权参数
Referer 黑白名单在控制台直接配。白名单只放我们的业务域名,连子域都别图省事加通配,一旦被滥用连你自己都拦不住。规则更新后全网生效有几分钟延迟,监控盯日志确认效果。
踩坑:防盗链的四个坑
第一个坑,空 Referer。直接打开链接(比如地址栏粘贴)时没有 Referer,严格白名单会误伤正常用户。打开允许空 Referer 的开关前先看自己业务的访问路径,内部工具与分享场景需求完全相反。
第二个坑,Referer 可伪造。Referer 是客户端发的,技术上一改一个准。防君子不防小人,真防盗还是得签名。把 Referer 当唯一防线的人,最后都会在日志里看到一排来自奇怪域名的 403 与一排伪装成正常域名的 200。
第三个坑,误伤自家业务。防盗链规则更新后,某次把移动端的请求拦死了,因为客户端网络层不发 Referer。上线防盗规则前,先灰度再全量,所有端都过一遍冒烟测试。
第四个坑,监控必须跟上。盗刷发生到我们发现之间有二十小时,这就是没有监控的代价。流量突增告警现在配在 5.3 监控告警里,阈值是日常三倍,任何时候超过都会叫我起床。
那次盗链事故我们做了完整复盘。凌晨流量曲线开始上翘,早上八点已达日常六倍,源头是某论坛帖子嵌了我们的公开素材。从异常到止血用了两小时,其中一小时在查日志确认来源。之后访问日志接入了实时聚合,任何域名异常引用都会在十分钟内浮出水面。
Referer 白名单配置有两个细节。其一,黑名单容易误伤,白名单才稳妥,默认拒绝是安全的默认姿态。其二,我们的业务域名和测试环境域名列表要同步维护,发版前核对,否则某天测试域被拦,排查能花掉一整个下午。
签名鉴权有三种模式可选,我们选了带过期时间戳的 C 型。签名的密钥只放在服务端,客户端永远拿不到,每次访问由后端动态签发。代价是每次访问都要经过一次签发逻辑,但它把内容控制权牢牢攥在自己手里。
IP 限频由 CDN 边缘直接执行,配置规则是单 IP 每秒五十次请求以下放行,超出触发拦截。规则上线第一天就拦住一个半夜扫站点的脚本,日志里一排 403 看着特别治愈。限频规则要定期复核,正常用户的访问模式变化了,规则也得跟着调。
应急流程演练过两次。发现盗链后的标准动作:先拉黑来源域名应急、再补 Referer 规则、最后评估是否开启签名鉴权。整个流程写成操作手册放在团队知识库里,谁值班都能照着做,不依赖任何人的临场反应。
APP 与小程序的请求 Referer 各不相同。小程序带固定 referer,APP 网络层可能完全不带。做规则前先把各端的真实请求样本抓一遍,对着样本配规则,比拍脑袋可靠一万倍。
日志分析是防盗链的侦察兵。每周跑一次 Referer 分布报表,来源域名按流量排序,新出现的域名逐一核对。有次发现一个小站点引用了我们一张图,流量很小,对方邮件说明是技术评测,我们就没追究。分级处理,既保全面子也守住底线。
防盗链与 CDN 计费要一起算。被白嫖的不只是内容,还有真金白银的流量费。那次盗链事故的直接损失是一千多的额外流量费,防盗链措施上线后次月回落到正常水平。安全投入的回报率在账单上写得清清楚楚。
白嫖与正常引用的界线要看场景。搜索引擎抓取、第三方客户端内嵌预览,这些可能带来真实用户的流量值得保留。一律封杀会把 SEO 也杀掉。我们的做法是新域名先观察一周再决定拉黑或放行,让子弹飞一会。
规则版本管理救过命。防盗链规则改了十几版,有次新规则误伤了自家小程序,十分钟内回滚到上一版。所有规则变更走配置中心带版本号,回滚是一键的事。线上规则没有版本管理,等于走钢丝不带保险绳。
安全事件要做季度回顾。把每季度的事故、近因、改进项摊在桌面上,你会发现防护措施总落后于攻击手段半步。接受这个现实,然后把监控与应急做到位,动态博弈是唯一正确的姿态。
团队里宣传防盗链意识比写规则更重要。开发同学知道公开桶的危险,自然不会随手把测试素材扔进公开目录。安全是设计出来的,更是习惯培养出来的。
防盗链规则上线前必须跑回归集。我们把各端请求样本录成回放集,每次规则变更全量回放,五分钟出结果。有次回放抓出对旧版客户端的误伤,上线前就解决了,这种稳赚不赔的投入多做不亏。
与 CDN 配合时注意规则执行顺序。Referer 校验、IP 限频、URL 鉴权都在边缘执行,顺序不同效果不同。我们的顺序是先便宜的再贵的:Referer 最先、限频其次、签名兜底,把计算留给最必要的场景。
被拉黑域主的反馈也要处理。有站长邮件申诉说引用是我们授权合作伙伴,走流程核对后放行。防盗链是手段不是目的,保持沟通的灰度让系统有人情味,也不会把潜在伙伴推成敌人。
新接入业务域名时自动加入白名单候选,但默认不生效。审批后由安全同学点亮,流程留痕。自动化的边界戛然而止在安全决策这一步,人最后拍板的环节不可省略。
防盗链之外还要防采集。有竞品用脚本整站拖公开素材,请求频率不高但持续不断,Referer 看不出来。后来是 4.4 的行为统计暴露了它:单 IP 覆盖全库的访问模式太特殊了。安全与统计再次证明了联动价值。
HTTPS 与防盗链协同。全站升级 HTTPS 后 Referer 传递更稳定,浏览器对降级请求会剥离 Referer,升级后误伤率明显下降。HTTPS 早已不是选择题。
给一组防护上线节奏建议:第一周只观察不拦截,第二周开 Referer,第三周再上限频,签名复杂度按需逐级加。一步到位的防护往往伴随大范围误伤,渐进式上线才是稳的。
白名单的维护责任要落到具体的人。我们的防盗链规则文档里写着负责人姓名与复核周期,规则再小都有归属。系统里没有负责人的配置,最后都会变成没人敢动的祖传代码。
防护规则要定期体检。每季度把白名单与黑名单拉出来过一遍,失效域名清掉、新增业务补上。规则库和代码一样会腐化,只是它腐化的时候不报错,只在你最忙的时候给你一刀。
做安全功能最大的收获是心态转变:从相信所有人,到默认不相信再用证据放行。这种心态前移到系统设计里,就是最小权限原则,网盘每个模块都因此受益。
有次安全例会上有人问,防盗链做到什么程度算够。我给的答案是:当盗链者觉得成本高于自己建站的成本,你就赢了。安全不追求绝对,追求的是攻防成本的不对称。
再补一个实操细节:所有防盗链规则的变更都选在周二上午执行。周一是例会地狱,周五没人想背锅,周二是全公司注意力最集中的窗口,出问题响应最快。
防盗链这一节写到最后,我反而想劝后来者一句:别只盯着防盗链,先把内容权限模型做对。公开桶里的东西没有防盗链能救,私有桶的东西不需要防盗链也能活。权限是本,防盗链是末,本末别倒置。
新工具上线前我们还会做一次盗链自检:模拟外部域名引用自家资源,看能不能拦住。自检脚本五分钟跑完,胜过上线后写事故复盘。安全领域的仪式感,都是事故教出来的。
最后交代一下收效。防盗链全套上线半年,公开资源的异常流量占比从百分之六降到零点三以下,每月挽回的流量费约两千元。安全投入的回报,在这张报表上写得一清二楚。
规则上线后的误伤名单要留档。我们把每次误伤的原因、时长、影响范围都记录在案,季度统计误伤率。数据让安全与体验的争论有了客观依据,不再是谁嗓门大谁有理。
与合作伙伴的资源对接也离不开防盗链。给正式合作方单独开白名单并配有效期,到期自动回收。授权这件事,口头承诺靠不住,系统规则才靠得住。
防盗链上线后我们做过一轮效果验收。第三方站点的嵌入请求拦截率九成以上,剩余一成来自合规合作方白名单。这个数字挂在我们季报里,是安全投入最好的成绩单。
白名单审批流程后来也产品化了。合作方在线提交申请,系统自动校验来源与流量后排队审批,通过即生效。流程线上化后,安全同学从跑断腿变成按审批钮。
小结
防盗链是一场攻防战,没有终局。合理的期望是把九成的白嫖挡掉,剩下的一成靠监控与应急。技术债务可以欠,安全债务连本带利结起来最快。
