盗链是一种损害原有网站合法利益,给原网站所在服务器造成额外负担的非法行为。要采取防盗链的措施,首先需要了解盗链的实现原理。 客户端向服务器请求资源时,为了减少网络带宽,提高响应时间,服务器一般不会一次将所有资源完整地传回给客户端。比如在请求一个网页时,首先会传回该网页的文本内容,当客户端浏览器在解析文本的过程中发现有图片存在时,会再次向服务器发起对该图片资源的请求,服务器将存储的图片资源再发送给客户端。在这个过程中,如果该服务器上只包含了网页的文本内容,并没有存储相关的图片资源,而是将图片资源链接到其他站点的服务器上去了,这就形成了盗链行为。
比如内网用户通过 Internet 访问域名为 www.test.com
这个服务器上的WEB服务,而该服务器没有存储图片资源,而是将图片链接到域名为 www.haicoder.net
服务器上,这就形成了盗链行为。这种情况下客户端请求图片资源实际上是来自其他的服务器。
要实现防盗链,需要了解 HTTP 协议中的请求头部的 Referer 头域和采用 URL 的格式表示访问当前网页或者文件的源地址。通过该头域的值,我们可以检测到访问目标资源的源地址。这样,如果我们检测到 Referer 头域中的值并不是自己站点内的 URL,就采取组织措施,实现防盗链。
需要注意是,由于 Referer 头域中的值可以被更改的,因此该方法不能完全阻止所有盗链行为。
防盗链的原理其实很简单,目前比较流行的做法就是通过 Referer 来进行判断和限制,Referer 的解释说明如下:
HTTP Referer 是 header 的一部分,当浏览器向 web 服务器发送请求的时候,一般会带上 Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。
简单来说,假如网站域名是haicoder.net
,我在 nginx 中设置,只允许 Referer 为 *.haicoder.net
的来源请求图片,其它网站来的一律禁止。这里我们需要用到 ngx_http_referer_module
模块和 $invalid_referer
变量。
referer_hash_bucket_size size;
默认值
referer_hash_bucket_size 64;
配置段
server, location
说明
这个指令在 nginx 1.0.5 中开始出现。
referer_hash_max_size
语法
referer_hash_max_size size;
默认值
referer_hash_max_size 2048;
配置段
server, location
说明
这个指令在 nginx 1.0.5 中开始出现。
valid_referers
语法
valid_referers none | blocked | server_names | string ...;
配置段
server, location
参数详解
参数 描述 none “Referer” 来源头部为空的情况,即表示空的来路,也就是直接访问,比如直接在浏览器打开一个图片。 blocked “Referer” 来源头部不为空,但是里面的值被代理或者防火墙删除了,这些值都不以 http:// 或者https:// 开头,即表示被防火墙标记过的来路。 server_names “Referer” 来源头部包含当前的 server_names(当前域名)。 string 任意字符串,定义服务器名或者可选的 URI 前缀。主机名可以使用 * 开头或者结尾,在检测来源头部这个过程中,来源域名中的主机端口将会被忽略掉。 regular expression 正则表达式,~ 表示排除 https:// 或 http:// 开头的字符串。 说明
指定合法的来源 ‘referer’, 它决定了内置变量 $invalid_referer 的值,如果 referer 头部包含在这个合法网址里面,这个变量被设置为 0,否则设置为 1。记住,不区分大小写的。
图片防盗链
图片防盗链的配置有三种方法:
方法一
针对不同文件类型的防盗链,配置示例一:
location ~* \.(gif|jpg|png|bmp)$ { valid_referers none blocked *.haicoder.net server_names ~\.google\. ~\.baidu\.; if ($invalid_referer) { return 403; #rewrite ^/ http://www.haicoder.net/403.jpg; }}
以上所有来至 haicoder.net 和域名中包含 google 和 baidu 的站点都可以访问到当前站点的图片,如果来源域名不在这个列表中,那么 $invalid_referer 等于 1,在 if 语句中返回一个 403 给用户,这样用户便会看到一个 403 的页面。
如果使用下面的 rewrite,那么盗链的图片都会显示 403.jpg,如果用户直接在浏览器输入你的图片地址,那么图片显示正常,因为它符合 none 这个规则。
配置示例二:
location ~ .*\.(wma|wmv|asf|mp3|mmf|zip|rar|jpg|gif|png|swf|flv)$ { valid_referers none blocked *.haicoder.net haicoder.net; if($invalid_referer){ #rewrite ^/ http://www.haicoder.net/error.html; return 403; }}
第一行:表示对
wma|wmv|asf|mp3|mmf|zip|rar|jpg|gif|png|swf|flv
后缀的文件实行防盗链。第二行:表示对
*.haicoder.net
和haicoder.net
这 2 个来路进行判断(*
代表任何,任何的二级域名),可以添加更多。
if{}
里面内容的意思是,如果来路不是指定来路就跳转到 403 错误页面,当然直接返回 404 也是可以的,也可以是图片。一般常用的图片防盗链的方法是在 server 或者 location 段中加入:
valid_referers none blocked www.haicoder.net haicoder.net;
如上面的两个小示例能起到一定的图片防盗链功能,但其实并不是真正的彻底的防盗链设置。一般来说,做好防盗链之后,其他网站盗链的本站图片就会全部失效无法显示,但是如果通过浏览器直接输入图片地址,仍然会显示图片,仍然可以右键图片另存为下载文件!
依然可以下载?这样就不是彻底的防盗了!那么,nginx 应该怎么样彻底地实现真正意义上的防盗链呢?首先,来看下 nginx 如何设置防盗链?
修改 nginx.conf 这个配置文件,默认图片是有过期时间设置的:
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d;}
把上面的配置修改成:
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { valid_referers none blocked *.haicoder.net haicoder.net; if($invalid_referer) { rewrite ^/ http://www.haicoder.net/404.jpg; #return404; } expires 30d;}
第一行:
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
,其中 “gif|jpg|jpeg|png|bmp|swf” 设置防盗链文件类型,自行修改,每个后缀用 “|” 符号分开!第二行:
valid_referers none blocked *.haicoder.net haicoder.net;
就是白名单,允许文件链出的域名白名单,自行修改成您的域名!*.haicoder.net
这个指的是子域名,域名与域名之间使用空格隔开!第四行:
rewrite ^/ http://www.haicoder.net/404.jpg;
这个图片是盗链返回的图片,也就是替换盗链网站所有盗链的图片。这个图片要放在没有设置防盗链的网站上,因为防盗链的作用,这个图片如果也放在防盗链网站上就会被当作防盗链显示不出来了,盗链者的网站所盗链图片会显示 X 符号。这样设置差不多就可以起到防盗链作用了,但是这样并不是彻底地实现真正意义上的防盗链!我们来看第二行:
valid_referers none blocked *.haicoder.net haicoder.net;
valid_referers 里多了 “none blocked”
我们把 “none blocked” 删掉,改成:valid_referers *.haicoder.net haicoder.net;
所以说,nginx 彻底地实现真正意义上的防盗链完整的代码应该是这样的:
- 去掉 valid_referers 后面的 none blocked
- 防盗链和 expires 图片过期时间设置整合到一起。其实就是保证 server 段中只有一个类似
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
的配置。完整配置如下:
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { valid_referers *.haicoder.net haicoder.net; if($invalid_referer) { rewrite ^/ http://www.haicoder.net/404.jpg; #return404; } expires 30d;}
这样您在浏览器直接输入图片地址就不会再显示图片出来了,也不可能会再右键另存什么的。
第四行:
rewrite ^/ http://www.haicoder.net/404.jpg;
这个是给图片防盗链设置的防盗链返回图片,如果我们是文件需要防盗链下载,把第四行改成一个链接,比如可以改成是主站的链接,rewrite ^/ http://www.haicoder.net;
这样,当别人输入文件下载地址,由于防盗链下载的作用就会跳转到您设置的这个链接!最后,配置文件设置完成别忘记重启 nginx 生效!另外注意:
- 请确保 server 段中只有一个
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
(比如还有另外的一个针对expires 过期时间的这样的 location 配置,那么必须要将其和防盗链的 location 整合到一起),否则可能导致代码无效,如有这个代码段请合并或删除。- 切记:如果要跳转到图片,记得替换的图片地址要使用没有防盗链的网站图片,否则由于替换的图片其实也处于防盗链情况下,会造成仍旧无法显示设置的图片。
方法二
针对目录的防盗链,这是 nginx 自带的防盗链功能:
location /img/ { root /data/img/; valid_referers none blocked *.haicoder.net haicoder.net; if($invalid_referer){ rewrite ^/ http://www.haicoder.net/images/error.gif; #return 403; }}location /images/ { alias /data/images/; valid_referers none blocked server_names *.haicoder.net haicoder.net ; if ($invalid_referer) { return 403; }}
方法三
使用第三方模块 ngx_http_accesskey_module 实现的防盗链。
案例
我们首先,使用 vim 打开 nginx 的默认配置路径,具体命令如下:
vim /etc/nginx/conf.d/default.conf
如下图所示:
我们执行如上命令,打开配置文件,并增加防盗链配置,具体配置如下:
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { valid_referers *.haicoder.net haicoder.net; if($invalid_referer) { rewrite ^/ http://www.haicoder.net/404.jpg; #return404; } expires 30d;}
加入之后,配置如下图所示:
现在,我们重新加载配置,即可生效。
Nginx防盗链配置总结
防盗链的原理其实很简单,目前比较流行的做法就是通过 Referer 来进行判断和限制,Referer 的解释说明如下:
HTTP Referer 是 header 的一部分,当浏览器向 web 服务器发送请求的时候,一般会带上 Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。