如何为Nginx 配置防盗链功能?

  • 2019 年 12 月 6 日
  • 筆記

开始之前
什么是 referer 请求头?

referer 请求头包含了当前请求页面的来源地址,即表示当前页面是通过这个来源页面里的链接进入的。

服务端一般使用referer 请求头识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。

利用 referer 防止盗链?

假设当一个 HTTP 请求头的 referer 字段中包含一些不正确(期望)的值

那么可以使用 nginx 的 ngx_http_referer_module 模块,禁止这个请求访问站点

也就是常说的 nginx 防盗链,不过需要注意的是,referer 请求头是可以伪造的,因此这个模块并不能 100%的阻止这类请求。

防盗链功能主要由模块中的 valid_referers 指令与 $invalid_referer 变量配合使用,例如下面的配置,允许符合以下规则的请求访问站点

  • 没有 referer,直接在浏览器打开这个URI。
  • 带有 referer,但是被修改过值(如proxy)不是以http(s)://开头的字符串。
  • 带有 referer, 值是以http(s)://开头的字符串,并且匹配 valid_referers列表中的值。

操作步骤


1. nginx 配置文件

cat /etc/nginx/conf.d/default.conf    server {       #..其它配置项目省略       # 上传图片目录      location ^~ /attachments {          alias /data/uploads/;          expires 180d;           valid_referers none blocked                                         *.demo.com demo.com                                         ~.demo.;         if ($invalid_referer) {              return 403;          }      }  }

2. 重启 nginx

nginx -t && nginx reload

3. 验证

4次请求,前3次为200,最后一次403 。

请求1,没有带`referer`信息,相当于直接在浏览器打开这个URI,匹配参数 "None"。    请求2,虽然有带`referer`信息,但值不是以"http(s)://"开头的字符串,匹配参数 "blocked"。    请求3,带有正确主机名`referer`信息,匹配参数 "server_names",这也是浏览器中正常请求。    请求4,带有域外的主机名`referer`信息,"表示这个请求是从百度页面里的链接进入的",按照规则                     $invalid_referer 变量被设置为 1 ,最终服务器返回 403状态码,完成防盗链。

valid_referers 指令

语法: valid_referers none|blocked|server_names string ...;  默认值: no  使用字段: server, location  功能: 此指令在 referer头的基础上为 $invalid_referer 变量赋值,可以实现简单的防盗链功能。  如果 valid_referers列表中没有匹配Referer请求头,$invalid_referer将被设置为1,否则为0(或空值)。
参数:  none      请求头中不存在 Referer字段('空值',比如直接在浏览器打开一个图片URI)。  blocked      请求头中存在 Referer字段,但值不是以"http(s)://"开头的字符串(被防火墙或代理服务器修改删除)。  server_names       Referer字段包含服务器名称。  arbitrary string      定义服务器名称和可选 URI前缀,服务器名称的开头或结尾可以有一个"*"。  regular expression      使用正则匹配,第一个符号为"~"。
示例:      valid_referers none blocked server_names                     *.example.com example.* www.example.org/galleries/                     ~.google.;        if ($invalid_referer) {          return 403;      }

参考

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Referer

http://nginx.org/en/docs/http/ngx_http_referer_module.html

小结


最后来总结下文章中的知识点

  • referer 请求头,用于识别访问来源。
  • referer 请求头可以伪造,不能做为唯一的判断条件。
  • 借助 ngx_http_referer_module 模块,实现简单的 nginx 防盗链。