站外有人直接把商品图挂到自己页面上。带宽账单一个月涨了四十多个G。运维加了防盗链,外站的图确实全变成裂图标。同一天客服反馈,用户在微信里打开商品页,图也是裂的。
常见的写法是valid_referers加一个if判断。列表里写了server_names和*.example.com,命中就放行,$invalid_referer为1就返回403。问题在于这个列表默认只放行带匹配来源的请求。来源为空的一律算非法。
微信内置浏览器、部分邮件客户端、从收藏夹直接打开的页面,发出去的请求都可能不带Referer。用户把图片地址粘到地址栏直接看,也是空的。这些请求全被那条403拦下,站内用户看到的就是裂图。另一类情况是页面在https下,图片走的还是http域名,浏览器按策略降级时不发来源头,同样落进拦截。
列表里补上none,允许来源为空的请求通过。补上blocked,放行被代理或防火墙抹掉来源的那些。这两项是关键字,不是域名,直接写在列表里即可。
只补这两项还不够,得把站内用到的所有域名都列全。主站在www.example.com,图片域名在img.example.com,手机站是m.example.com,图片又走了一层CDN,CDN的回源域名是cdn.example.com。少写一个,那个入口的图就全裂。列表支持通配符,写成*.example.com可以一次盖住所有子域,但盖不住裸域example.com,两个都要写。站点换过域名、老域名还在跳转的,老域名也得留在列表里,否则从搜索引擎点进来的老链接,图是坏的。还有一个位置容易漏,后台编辑器和客服系统这类独立子域,它们的域名往往不在最初整理的清单里。
你要判断到底拦了谁,看访问日志里图片请求的状态码和来源。403集中在哪几个来源,一目了然。用curl带-e参数模拟一次,带站内地址和不带各试一遍,两边的返回码不一样就说明规则本身在起作用。
改完先别急着全面放开,把none加进去之后观察一天。真正的盗链站是带来源的,它们伪造一个假来源照样能过,所以这一层只能挡住直接抄地址的那批。
现在列表里是none、blocked、server_names、*.example.com、example.com,加上CDN回源域名,一共六项。上线之后外站流量掉到原来的三成,站内裂图的反馈也停了。要注意的是这套规则挡不住把图下载下来再上传的人,那属于版权问题,靠水印和取证。带宽这块还可以在CDN上按来源做限速,两层一起用效果更稳。
规则写在图片所在的location里最稳;写在server块顶层同样生效,但内层location一旦另写一条valid_referers,就以内层为准。改完用nginx -t验一遍再reload,这批配置语法上不复杂,出错多在域名漏了一项。
A5创业网 版权所有