Nginx防盗链配置

什么是盗链

盗链是一种损害原有网站合法利益,给原网站所在服务器造成额外负担的非法行为。要采取防盗链的措施,首先需要了解盗链的实现原理。 客户端向服务器请求资源时,为了减少网络带宽,提高响应时间,服务器一般不会一次将所有资源完整地传回给客户端。比如在请求一个网页时,首先会传回该网页的文本内容,当客户端浏览器在解析文本的过程中发现有图片存在时,会再次向服务器发起对该图片资源的请求,服务器将存储的图片资源再发送给客户端。在这个过程中,如果该服务器上只包含了网页的文本内容,并没有存储相关的图片资源,而是将图片资源链接到其他站点的服务器上去了,这就形成了盗链行为。

比如内网用户通过 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 变量。

Nginx防盗链指令

referer_hash_bucket_size

语法

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.nethaicoder.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 彻底地实现真正意义上的防盗链完整的代码应该是这样的:

  1. 去掉 valid_referers 后面的 none blocked
  2. 防盗链和 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 生效!

另外注意:

  1. 请确保 server 段中只有一个 location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$(比如还有另外的一个针对expires 过期时间的这样的 location 配置,那么必须要将其和防盗链的 location 整合到一起),否则可能导致代码无效,如有这个代码段请合并或删除。
  2. 切记:如果要跳转到图片,记得替换的图片地址要使用没有防盗链的网站图片,否则由于替换的图片其实也处于防盗链情况下,会造成仍旧无法显示设置的图片。

方法二

针对目录的防盗链,这是 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

如下图所示:

63_nginx防盗链配置.png

我们执行如上命令,打开配置文件,并增加防盗链配置,具体配置如下:

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;}

加入之后,配置如下图所示:

64_nginx防盗链配置.png

现在,我们重新加载配置,即可生效。

Nginx防盗链配置总结

防盗链的原理其实很简单,目前比较流行的做法就是通过 Referer 来进行判断和限制,Referer 的解释说明如下:

HTTP Referer 是 header 的一部分,当浏览器向 web 服务器发送请求的时候,一般会带上 Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。