防盗链原理和实践

2020-10-23

前言

最近巡检nginx日志,发现图片有异常的站外访问。显然有人未经我同意,抄袭我原创的内容,整篇复制HTML内容,连<img>标签里的src都不会改。他网站上访客浏览内容时,图片消耗的是我服务器的流量。

即日起,本站所有配图均添加了防盗链的配置。本文介绍一下防盗链原理和实践经验。


如何防盗链

在http协议的header里,有一个Referer字段,用于标识访问来源。Referer实际上是 "referrer" 误拼写,意思是“推荐人”。对于加载静态资源(图片、JS、CSS等),浏览器会自动带上当前页面的网址。服务器可以用这个作为判断,来禁止本站以外的访问。


以本博客为例,在nginx里增加如下配置:

location ~* \.(gif|jpg|png)$ {    
  valid_referers blocked *.oonne.com;    
  if ($invalid_referer) {        
    return 403; 
  }
}


此处用到的是nginx的ngx_http_referer_module模块。外面用location路由匹配图片资源,valid_referers表示可信的referer。当本次访问的referer可信时,内置变量$invalid_referer的值为空字符串;不可信时,内置变量$invalid_referer的值为1。以此做if条件判断,对不可信的请求返回状态码403。


valid_referers可选的参数有这些:


如何绕过防盗链

为了方便下载图片,很多网站的防盗链机制不会限制空的Referer。因此盗链者只需要制造一个空的Referer就行了:


如果在浏览器以外的场景,没有了浏览器的限制,伪造Referer就更容易了,直接改http header即可。因此,上述防盗链方案仅仅是提高了技术门槛,限制多数普通用户,增加盗链的难度。


如何防止被绕过

禁止为空的Referer:在浏览器里右键打开图片,或者右键下载图片,都会带上原有的Referer。真实用户直接复制图片链接去访问的情况非常少。因此推荐不允许图片的Referer为空。


禁止被iFrame嵌套:可以在http header中配置 X-Frame-Options 为 “deny” 来防止网站和资源被嵌到别人的站点里。即使迫不得已需要用到iFrame,也建议在 X-Frame-Options 中配置可信的域名。

CSP配置也可以对iFrame嵌套做限制,但是旧的浏览器支持并不完整,建议两者配合使用。


如果想对网站的资源做更严格的限制,比如登录之后才能看到图片,可以先种一个cookie。静态资源的请求也是会带上cookie的,服务端再做校验即可。


还可以使用动态文件名,图片资源每次访问的链接地址都是随机生成的,每次的地址都有时效性。很多CDN都有这样的功能。


总结

道高一尺,魔高一丈。防盗链机制做得再好,也防不住直接下载图片再发到别的网站上。还是希望各位看官能尊重一下原创内容。



参考文献

  1. https://tools.ietf.org/html/rfc7231#section-5.5.2



本文未经许可禁止转载,如需转载关注微信公众号【工程师加一】并留言。