[root@www nginx-1.16.1]# ./configure --help | grep referer
--without-http_referer_module ---该模块可以进行防盗链设置,该模块是默认编译进Nginx里面的
客户端向服务器请求资源时,为了减少网络带宽,提高响应时间,服务器一般不会一次将所有资源完整地传回给客户端。比如在请求一个网页时,首先会传回该网页的文本内容,当客户端浏览器在解析文本的过程中发现有图片存在时,会再次向服务器发起对该图片资源的请求,服务器将存储的图片资源再发送给客户端。在这个过程中,如果该服务器上只包含了网页的文本内容,并没有存储相关的图片资源,而是将图片资源链接到其他站点的服务器上去了,这就形成了盗链行为
要实现防盗链,需要了解HTTP协议中的请求头部的Referer头域和采用URL的格式表示访问当前网页或者文件的源地址。通过该头域的值,我们可以检测到访问目标资源的源地址。这样,如果我们检测到Referer头域中的值并不是自己站点内的URL,就采取组织措施,实现防盗链。需要注意是,由于Referer头域中的值可以被更改的,因此该方法不能完全阻止所有盗链行为。
首先,需要理解一个nginx变量:
$http_referer
表示当前请求上一次页面访问的地址
换句话说,访问 www.baidu.com 主页,这是第一次访问,所以 $http_referer 为空
但是 访问此页面的时候还需要获取一张首页图片,再请求这张图片的时候 $http_referer 就为 www.baidu.com
HTTP Referer是Header的一部分,当浏览器向Web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器借此可以获得一些信息用于处理,例如防止未经允许的网站盗链图片、文件等。因此HTTP Referer头信息是可以通过程序来伪装生成的,所以通过Referer信息防盗链并非100%可靠,但是,它能够限制大部分的盗链情况。
该指令"valid_referers"的语法:
valid_referers [none|blocked|server_names] ...
默认值:none
使用环境:server,location
Nginx配置中由一个指令valide_referers,用来获取Referer头域中的值,并且根据该值的情况给Nginx全局变量$invalid_referer赋值。如果Referer头域中没有符合valid_referers指令的值,$invalid_referer变量将会被赋值为1。
该指令会根据Referer Header头的内容分配一个值为0或1给变量$invalid_referer。如果Referer Header头不符合valid_referers指令设置的有效,变量$invalid_referer将被设置为1.
该指令的参数可以为下面的内容
valid_referers 表示合法的referers设置
none: 表示无Referer值的情况,直接通过浏览器或者其他工具访问。
blocked: 表示有referers,但是值被代理服务器或者防火墙隐藏;
server_names:表示一个或多个主机名称。从Nginx 0.5.33版本开始,server_names中可以使用通配符"*"号。lutixia.net 表示通过lutixia.net访问的referers,*.jfedu.net: 表示通过*.jfedu.net访问的referers,*表示任意host主机。
再说的通俗一点:
valid_referers 定资源访问是通过以下几种方式为合法,即白名单
none: 允许缺失的头部访问
blocked: 允许referer没有对应值的请求
Referer到底是什么东西?我的nginx配置文件很简单,打开autoindex功能,即将整个目录列出来。然后将默认的index.html文件修改为index.html.bak,同时在目录下面创建一个jfedu.html文件
[root@www ~]# vim /usr/local/nginx/conf/vhost/www.test.com.conf
server {
listen 80;
server_name www.test.com;
charset utf-8;
root /data/www/test;
location /{
autoindex on;
}
}
[root@www ~]# ll /data/www/test/
total 12
-rw-r--r-- 1 root root 338 Apr 21 09:28 404.html
-rw-r--r-- 1 root root 494 Apr 21 09:28 50x.html
-rw-r--r-- 1 root root 26 Apr 21 10:21 jfedu.html
来到主页,可以看到将文件目录全部列出来,我们要通过jfedu.html这个文件来做测试
下面图片的方式是通过在网页内通过鼠标点击jfedu.htm来访问该资源,可以看到是有Reference的值的,当前的reference信息就是当前网页的信息。可以看出从当前网页内访问的资源的Reference是有值的,即当前网页的信息。
下面这张图片是通过在网址栏输入资源地址直接访问的,不是通过鼠标在网站内点击访问,可以看到Reference的值是不存在的。直接输入链接标准的IP+资源是不存在Reference的值的。(匹配到的none)
这是一个正则匹配,如果是以.gif,jpg,png,swf,flv结尾的文件,就匹配这个location规则,这些规则定义就是两个花括号里面的内容。
location ~* \.(gif|jpg|png|swf|flv)$ {
valid_referers none blocked www.test.com *.jfedu.net;
root /usr/share/nginx/html;
if ($invalid_referer) {
return 403;
}}
location ~* \.(gif|jpg|png|swf|flv)${}为设置防盗链的文件类型,使用竖线|分隔。~*表示忽略大小写,只要是访问以.gif jpg png swf flv结尾的请求就匹配花括号里面的规则
valid_referers www.test.com *.jfedu.net;为白名单,使用空格分隔,可以使用*进行泛域名设置。
if ($invalid_referer) {}为判断是否符合白名单,不符合白名单将执行{}内的内容。
总结就是:以上所有来自lutixia.net *.jfedu.net的站点都可以访问到当前站点的图片,如果来源域名不在这个列表中,那么$invalid_referer等于1,在if语句中返回一个403给用户,这样用户便会看到一个403的页面。
测试192.168.179.179.100去盗用192.168.179.99的图片
(1)在192.168.179.100上配置下面信息去盗用192.168.179.99的图片jfedu.png
[root@localhost nginx-1.16.1]# vim /usr/local/nginx/html/jfedu.html
[root@localhost nginx-1.16.1]# cat /usr/local/nginx/html/jfedu.html
this is 192.168.179.100
(2)192.168.179.99提供图片给100去盗取
[root@www nginx-1.16.1]# cp /usr/share/httpd/icons/icon.sheet.png /usr/local/nginx/html/jfedu.png
可以看到没加上防盗链规则192.168.179.100可以去盗用192.168.179.99的图片
[root@www nginx-1.16.1]# vim /usr/local/nginx/conf/nginx.conf --加上防盗链规则,注意要把自己的IP加上
location ~* \.(gif|jpg|png|swf|flv)$ {
valid_referers none blocked 192.168.179.99 lutixia.net *.jfedu.net;
root /usr/local/nginx/html;
if ($invalid_referer) {
return 403;
} }
[root@www ~]# /usr/local/nginx/sbin/nginx -s reload --重启服务
可以看到加上防盗链规则之后盗取失败了,返回403状态码
再来看看192.168.179.99的日志信息,可以看到请求的资源是jfedu.png,但是referrer并不是本机,这是一个盗链。