这里需要使用两台Linux主机(一台充当防盗链服务器,一台充当盗链服务器),下表是它们所使用的操作系统以及IP地址。
两台Linux主机所使用的操作系统以及IP地址 |
||
主机名称 |
操作系统 | IP地址 |
防盗链服务器 | CentOS7.5 | 192.168.5.23 |
盗链服务器 | CentOS6.10 | 192.168.5.154 |
两台Linux主机的Nginx采用yum安装,版本都是1.16.1
一、nginx模块ngx_http_referer_module指令简介
nginx中ngx_http_referer_module模块允许拦截“Referer”请求头中含有非法值的请求,阻止它们访问站点。 需要注意的是伪造一个有效的“Referer”请求头是非常容易的, 因此这个模块的预期目的不在于彻底地阻止这些非法请求,而是为了阻止由正常浏览器发出的大规模此类请求(提高了技术门槛,可以限制多数普通用户)。 还有一点需要注意,即使正常浏览器发送的合法请求,也可能没有“Referer”请求头,所以有时候不能拒绝来源头部“Referer”为空的请求。
防盗链配置语法
语法:valid_referers none | blocked | server_names | string ...;
可以配置在server或者location节点里
参数说明
none:缺少“Referer” 请求头的情况;
blocked:“Referer”请求头存在,但是它的值被代理服务器或者防火墙删除了,所以无法跟据“Referer”的值来进行拦截,这些值都不以“http://”或者“https://”字符串作为开头;
server_names:“Referer”请求头包含某个虚拟主机名;
string ...:任意字符串定义一个服务器名或者可选的URI前缀,服务器名可以使用“*”开头或者结尾,当Nginx在检测请求头时,“Referer”请求头里的服务器端口将会被忽略掉;
正则表达式:必须以“~”符号作为开头。 需要注意的是表达式会从“http://”或者“https://”之后的文本开始匹配。
二、图片盗链配置
vim /etc/nginx/conf.d/default.conf
每次修改完配置文件,重启 Nginx 或者执行 nginx -s reload 才会生效,务必记得。
# location / {
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$ {
root /usr/share/nginx/html;
index index.html index.htm;
valid_referers none blocked *.opsdrip.cn 192.168.5.154 server_names ~.google. ~aidu.;
if ($invalid_referer){
return 403;
# rewrite ^/ http://opsdrip.cn/403.jpg;
}
}
在 location 节点里配置,截图如下:
下面以截图中的行数做个简单的说明:
第8行:location /
代表一个过滤器,/匹配所有请求,这里注释了
第9行:location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
其中“gif|jpg|jpeg|png|bmp|swf”设置防盗链文件类型,可自定义,每个后缀用“|”符号分开。
第13行:valid_referers none blocked *.opsdrip.cn 192.168.5.155 server_names ~.google. ~aidu.;
就是白名单,允许文件链出的域名或者IP地址白名单,所有来自opsdrip.cn、IP地址192.168.5.154和域名中包含google和baidu的站点都可以访问到当前站点的图片,如果来源域名不在这个列表中,那么$invalid_referer等于1,在 if 语句中返回一个403状态给用户,自行修改成自己的域名或者IP地址,域名(IP地址)与域名(IP地址)之间使用空格隔开。
第15行:return 403;
盗链返回一个403的状态码。
第16行:rewrite ^/ http://opsdrip.cn/403.jpg;
这个图片是盗链返回的图片,也就是替换盗链网站所有盗链的图片。这个图片要放在没有设置防盗链的网站上,因为防盗链的作用,这个图片如果也放在防盗链网站上就会被当作防盗链显示不出来,这里注释了,选择只返回一个403状态码。
在防盗链服务器的 /usr/share/nginx/html/ 目录下上传一张1.jpg的图片
在盗链服务器的 /usr/share/nginx/html/ 目录下新建一个html页面,代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>防盗链测试</title>
</head>
<body>
<h1>Hello!</h1>
<img src="http://192.168.5.23/1.jpg"> <!-- 引入防盗链服务器上的图片 -->
</body>
</html>
在浏览器访问html页面,如下:
修改防盗链服务器的配置,(将IP地址改为192.168.5.155):
# location / {
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$ {
root /usr/share/nginx/html;
index index.html index.htm;
valid_referers none blocked *.opsdrip.cn 192.168.5.155 server_names ~.google. ~aidu.;
if ($invalid_referer){
return 403;
# rewrite ^/ http://opsdrip.cn/403.jpg;
}
}
再次访问html页面,如下:
F12,查看,图片的状态为403
防盗链服务器Nginx日志中变量 $http_referer 也能够看到访问资源的链接是谁
这里做好防盗链之后其他网站盗链的本站图片就会全部失效无法显示,但是如果通过浏览器直接输入图片地址,仍然会显示图片,仍然可以右键另存为图片(因为它符合none这个规则,去掉参数“none”可以防止这种情况),甚至可以直接绕过防盗链的设置(比如在html页面的<head>里,加上这一句<meta name="referrer" content="never">,做一个伪签名,就可以轻松绕过防盗链)。
这样就不是彻底的防盗了!那么,Nginx应该怎么样彻底地实现真正意义上的防盗链呢?
修改Nginx的配置,把“none blocked”删掉,如下:
# location / {
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$ {
root /usr/share/nginx/html;
index index.html index.htm;
valid_referers *.opsdrip.cn 192.168.5.154 server_names ~.google. ~aidu.;
if ($invalid_referer){
return 403;
# rewrite ^/ http://opsdrip.cn/403.jpg;
}
}
浏览器再次访问盗链服务器上的html页面
直接访问防盗链服务器上的图片,也会显示403,如下:
图片使用请求头做防盗链,只能限制基本的图片盗用,无法防止图片采集。
本文参考自: