日常运维工作中,设置防盗链的需求会经常碰到,这也是优化网站的一个必要措施。今天在此介绍Nginx中设置下载防盗链和图片防盗链的操作~

一、Nginx中下载防盗链的操作记录
对于一些站点上的下载操作,有很多的下载来源不是本站,是迅雷、flashget, 源源不断的带宽,防盗链绝对是当务之急!使用来源判断根本不靠谱,只能防止一些小白站点的盗链,迅雷之类的下载工具完全无效;
如果是nginx配置的站点,可以使用secure link来完美解决这个问题,远离迅雷.

以下Nginx的盗链配置,仅用于下载服务器的下载防盗链,不适用于图片防盗链:
1)nginx的配置
[root@test-huanqiu ~]# cat /usr/local/nginx/conf/vhost/down.conf

server {

    listen       80;
    server_name  x1.down.wangshibo.com;
    access_log  /data/logs/nginx/x1.down.wangshibo.com.access.log  main;

    index index.html index.php index.html;
    root /data/site/x1.down.wangshibo.com;

    location / {
        secure_link $arg_st,$arg_e;
        secure_link_md5 wangshibo.com$uri$arg_e;

        if ($secure_link = "") {
            return 403;
        }

        if ($secure_link = "0") {
            return 403;
        }
    }
}

2)php下载页面
[root@test-huanqiu ~]# cd /data/site/x1.down.wangshibo.com
[root@test-huanqiu x1.down.wangshibo.com]# cat down.php
<?php
# 作用:生成nginx secure link链接
# 站点:www.wangshibo.com
$secret = 'wangshibo.com';          # 密钥
$path = '/web/nginx-1.4.2.tar.gz';    # 下载文件
# 下载到期时间,time是当前时间,300表示300秒,也就是说从现在到300秒之内文件不过期
$expire = time()+300;
# 用文件路径、密钥、过期时间生成加密串
$md5 = base64_encode(md5($secret . $path . $expire, true));
$md5 = strtr($md5, '+/', '-_');
$md5 = str_replace('=', '', $md5);
# 加密后的下载地址
echo '<a href=http://x1.down.wangshibo.com/web/nginx-1.4.2.tar.gz?st='.$md5.'&e='.$expire.'>nginx-1.4.2</a>';
echo '<br>http://x1.down.wangshibo.com/web/nginx-1.4.2.tar.gz?st='.$md5.'&e='.$expire;
?>

3)测试nginx防盗链
浏览器上打开http://test.wangshibo.com/down.php点击上面的连接下载
下载地址如下:
http://x1.down.wangshibo.com/web/nginx-1.4.2.tar.gz?st=LSVzmZllg68AJaBmeK3E8Q&e=1378881984
页面不要刷新,等到5分钟后在下载一次,你会发现点击下载会跳转到403页面。

4)secure link 防盗链过程
1.用户访问down.php
2.down.php根据secret密钥、过期时间、文件uri生成加密串
3.将加密串与过期时间作为参数跟到文件下载地址的后面
4.nginx下载服务器接收到了过期时间,也使用过期时间、配置里密钥、文件uri生成加密串
5.将用户传进来的加密串与自己生成的加密串进行对比,一致允许下载,不一致403
整个过程实际上很简单,类似于用户密码验证. 尤为注意的一点是一定不要泄露了自己的密钥,否则别人就可以盗链了,除了泄露之外最好能经常更新密钥.

5)secure link 指令
1.secure_link
语法: secure_link md5_hash[,expiration_time]
默认: none
配置段: location
variables: yes
这个指令由uri中的MD5哈希值和过期时间组成. md5哈希必须由base64加密的,过期时间为unix时间.如果不加过期时间,那么这个连接永远都不会过期.
2.secure_link_md5
语法: secure_link_md5 secret_token_concatenated_with_protected_uri
默认: none
配置段: location
variables: yes
md5值对比结果,使用上面提供的uri、密钥、过期时间生成md5哈希值.如果它生成的md5哈希值与用户提交过来的哈希值一致,那么这个变量的值为1,否则为0
3.secure_link_secret
语法: secure_link_secret word
默认:
配置段: location
Reference: secure_link_secret
nginx 0.8.50之后的版本已经使用secure_link_md5取代,不在多说.

注意事项
1.密钥防止泄露、以及经常更新密钥
2.下载服务器和php服务器的时间不能相差太大,否则容易出现文件一直都是过期状态.

secure link以及内置到了nginx,不需要额外安装第三方模块,有下载服务器的情况,极力推荐使用它,除非你不在乎你的带宽.

6)珍爱带宽,远离迅雷
还可以配置nginx,让nginx防止迅雷、快车的多线程下载:
作用域: server location
if ($http_range)
{
return 405;
}

这样给用户端的第二个线程返回405,只让nginx单线程给用户吐数据。

二、Nginx中图片防盗链的操作记录
图片防盗链和下载防盗链使用的指令不同,下载防盗链使用secure link,并且需要程序配合,但是效果非常好;而图片防盗链不需要程序配合,根据图片来源来实现,但是只能先限制基本的图片盗用,无法防止图片采集.
nginx referer指令简介
nginx模块ngx_http_referer_module通常用于阻挡来源非法的域名请求.我们应该牢记,伪装Referer头部是非常简单的事情,所以这个模块只能用于阻止大部分非法请求.我们应该记住,有些合法的请求是不会带referer来源头部的,所以有时候不要拒绝来源头部(referer)为空的请求.

nginx防盗链指令
1)语法: referer_hash_bucket_size size;
默认值: referer_hash_bucket_size 64;
配置段: server, location
这个指令在nginx 1.0.5中开始出现.
2)语法: referer_hash_max_size size;
默认值: referer_hash_max_size 2048;
配置段: server, location
这个指令在nginx 1.0.5中开始出现.
3)语法: valid_referers none | blocked | server_names | string ...;
默认值: —
配置段: server, location
指定合法的来源'referer', 它决定了内置变量$invalid_referer的值,如果referer头部包含在这个合法网址里面,这个变量被设置为0,否则设置为1.记住,不区分大小写的.

参数说明
none:“Referer” 来源头部为空的情况,即表示空的来路,也就是直接访问,比如直接在浏览器打开一个图片
blocked:“Referer”来源头部不为空,但是里面的值被代理或者防火墙删除了,这些值都不以http://或者https://开头.即表示被防火墙标记过的来路
server_names:“Referer”来源头部包含当前的server_names(当前域名)
string:任意字符串,定义服务器名或者可选的URI前缀.主机名可以使用*开头或者结尾,在检测来源头部这个过程中,来源域名中的主机端口将会被忽略掉
regular expression:正则表达式,~表示排除https://或http://开头的字符串.

注意:
图片使用来源头部做防盗链是最合理的. 简单、实用。但是没有办法防采集。

图片防盗链的配置有三种方法,下面一一介绍:
1)针对不同文件类型的防盗链:
配置示例1:
location ~* \.(gif|jpg|png|bmp)$ {
      valid_referers none blocked *.wangshibo.com server_names ~\.google\. ~\.baidu\.;
      if ($invalid_referer) {
         return 403;
        #rewrite ^/ http://www.wangshibo.com/403.jpg;
      }
}

配置说明:
以上所有来至wangshibo.com和域名中包含google和baidu的站点都可以访问到当前站点的图片
如果来源域名不在这个列表中,那么$invalid_referer等于1,在if语句中返回一个403给用户,这样用户便会看到一个403的页面;
如果使用下面的rewrite,那么盗链的图片都会显示403.jpg;
如果用户直接在浏览器输入你的图片地址,那么图片显示正常,因为它符合none这个规则.

配置示例2:
location ~ .*\.(wma|wmv|asf|mp3|mmf|zip|rar|jpg|gif|png|swf|flv)$ {
     valid_referers none blocked *.wangshibo.com wangshibo.com;
     if($invalid_referer){
         #rewrite ^/ http://www.765h.com/error.html;
         return 403;
     }
}

配置说明:
第一行:表示对wma|wmv|asf|mp3|mmf|zip|rar|jpg|gif|png|swf|flv后缀的文件实行防盗链
第二行:表示对*.wangshibo.com和wangshibo.com这2个来路进行判断(*代表任何,任何的二级域名),可以添加更多
if{}里面内容的意思是,如果来路不是指定来路就跳转到403错误页面,当然直接返回404也是可以的,也可以是图片。

一般常用的图片防盗链的方法是在server或者location段中加入:
valid_referers none blocked www.wangshibo.com wangshibo.com;
如上面的两个小示例能起到一定的图片防盗链功能,但其实并不是真正的彻底的防盗链设置。
一般来说:
做好防盗链之后,其他网站盗链的本站图片就会全部失效无法显示,但是如果通过浏览器直接输入图片地址,仍然会显示图片,仍然可以右键图片另存为下载文件!
依然可以下载?这样就不是彻底的防盗了!那么,nginx应该怎么样彻底地实现真正意义上的防盗链呢?

首先,来看下nginx如何设置防盗链?
修改 /usr/local/nginx/conf/nginx.conf 这个配置文件:
默认图片是有过期时间设置的
[root@bastion-IDC ~]# vim /usr/local/nginx/conf/nginx.conf
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
   expires 30d;
}

把上面的配置修改成:
[root@bastion-IDC ~]# vim /usr/local/nginx/conf/nginx.conf
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
    valid_referers none blocked *.wangshibo.com wangshibo.com;
    if($invalid_referer) {
       rewrite ^/ http://www.wangshibo.com/404.jpg;
      #return404;
    }
    expires 30d;
}

配置解说:
第一行:location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
其中“gif|jpg|jpeg|png|bmp|swf”设置防盗链文件类型,自行修改,每个后缀用“|”符号分开!

第二行:valid_referers none blocked *.wangshibo.com wangshibo.com;
就是白名单,允许文件链出的域名白名单,自行修改成您的域名!*.wangshibo.com这个指的是子域名,域名与域名之间使用空格隔开!

第四行:rewrite ^/ http://www.wangshibo.com/404.jpg;
这个图片是盗链返回的图片,也就是替换盗链网站所有盗链的图片。这个图片要放在没有设置防盗链的网站上,因为防盗链的作用,这个图片如果也放在防盗链网站上就会被当作防盗链显示不出来了,盗链者的网站所盗链图片会显示X符号。

这样设置差不多就可以起到防盗链作用了,但是这样并不是彻底地实现真正意义上的防盗链!
我们来看第二行:valid_referers none blocked *.wangshibo.com wangshibo.com;
valid_referers 里多了“none blocked”
我们把“none blocked”删掉,改成:
valid_referers *.wangshibo.com wangshibo.com;

所以说:
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 *.wangshibo.com wangshibo.com;
  if($invalid_referer) {
    rewrite ^/ http://www.wangshibo.com/404.jpg;
    #return404;
    }
  expires 30d;
}

这样您在浏览器直接输入图片地址就不会再显示图片出来了,也不可能会再右键另存什么的。
第四行:
rewrite ^/ http://www.wangshibo.com/404.jpg;
这个是给图片防盗链设置的防盗链返回图片
如果我们是文件需要防盗链下载,把第四行改成一个链接,比如可以改成是主站的链接
rewrite ^/ http://www.wangshibo.com;
这样,当别人输入文件下载地址,由于防盗链下载的作用就会跳转到您设置的这个链接!
最后,配置文件设置完成别忘记重启nginx生效!

再看一例:
比如现在google首页点击广告www.abc.com跳转到www.baidu.com,但是直接在浏览器输入www.abc.com,还是www.abc.com
配置如下:
valid_referers none blocked localhost *.abc.com abc.com;
   if ($invalid_referer){
     rewrite ^/(.*) http://www.baidu.com/? permanent;
     break;
   }

------------------------------------------------------------------------------------------------------------------------------
实验说明:
[root@test-huanqiu ~]# vim /usr/local/nginx/conf/vhosts/image.conf

server {
     listen 80 ;
     server_name 192.168.1.14 web01.wangshibo.cn;
     root /var/www/html;
     index index.html index.php index.htm;

     location ~* \.(gif|jpg|png|swf|flv)$ {
     valid_referers none blocked *.wangshibo.cn;
     if ($invalid_referer) {
         rewrite ^/ http://www.heihei.com/404.jpg;
         #return 404;
         }
      expires 30d;
     }

     location ~ .*\.(php|php5)?$ {
       #fastcgi_pass  unix:/tmp/php-cgi.sock;
       fastcgi_pass  127.0.0.1:9000;
       fastcgi_index index.php;
       include fastcgi.conf;
     }
     access_log  /usr/local/nginx/logs/image.log;
 }

注意第8行 "valid_referers none blocked"
其中"none" "blocked" 的意思分别是:
none代表没有referer;
blocded代表有referer但是被防火墙或者是代理给去除了。

以上配置后,访问的跳转流程:
1)首先当输入要打开的网址的时候,因为是直接输入的没有referer,所以匹配了valid_referers后面的none或者是blocked,invalid_referer值为0,因此不进行跳转.
2)当是从这个网站里面的链接跳到该网站首页的时候,因为referer的值是肯定包含srever_names,所以匹配了server_names,因此不进行跳转;
3)当从搜素引擎进去的时候因为referer字段类似于www.google.com.hk/search,开始进行匹配,发现没有一个匹配,则此时会设置invalid_referer值为1,if语句成功执行,进行了跳转. 达到功能!

[root@test-huanqiu ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@test-huanqiu ~]# /usr/local/nginx/sbin/nginx -s reload

只有把这两个none,blocked去掉,才可以真正的实现防盗连!因为只有匹配到server_name的时候,才不会进行跳转。如下说明:

[root@master-node html]# ll /var/www/html/
total 16
-rw-r--r-- 1 www www 143 Dec 14 11:34 index.html
-rw-r--r-- 1 www www 10571 Dec 14 11:35 long.jpg
[root@master-node html]# cat /var/www/html/index.html

<html>
<body>
<h1>"王士博",welcome to beijing!! </h1>
<img alt="long.jpg" src="/long.jpg" height="auto" width="auto"></img>
</body>
</html>

访问,看看效果:

接真输入图片地址可以显示图片:

现在将none,blocked去掉,看看效果:
[root@test-huanqiu ~]# vim /usr/local/nginx/conf/vhosts/image.conf

server {
     listen 80 ;
     server_name 192.168.1.14 web01.wangshibo.cn;
     root /var/www/html;
     index index.html index.php index.htm;

     location ~* \.(gif|jpg|png|swf|flv)$ {
     valid_referers *.wangshibo.cn;
     if ($invalid_referer) {
         rewrite ^/ http://www.heihei.com/404.jpg;
         #return 404;
         }
      expires 30d;
     }

     location ~ .*\.(php|php5)?$ {
       #fastcgi_pass  unix:/tmp/php-cgi.sock;
       fastcgi_pass  127.0.0.1:9000;
       fastcgi_index index.php;
       include fastcgi.conf;
     }
     access_log  /usr/local/nginx/logs/image.log;
 }

[root@test-huanqiu ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@test-huanqiu ~]# /usr/local/nginx/sbin/nginx -s reload

再次访问

当再次访问http://web01.wangshibo.cn/long.jpg时就会跳转到http://www.heihei.com/404.jpg(测试时,记得删除浏览器缓存。nginx中有图片缓存配置)

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

------------------------------------------------------------------------------------------------------------------------------

2)针对目录的防盗链:( 这是nginx自带的防盗链功能。)
location /img/ {
root /data/img/;
valid_referers none blocked *.wangshibo.com wangshibo.com;
if($invalid_referer){
rewrite ^/ http://www.wangshibo.com/images/error.gif;
#return 403;
}
}

location /images/ {
alias /data/images/;
valid_referers none blocked server_names *.wangshibo.com wangshibo.com ;
if ($invalid_referer) {
return 403;
}
}

3)使用第三方模块ngx_http_accesskey_module实现的防盗链:
1.下载Nginx和nginx-http-access模块
http://nginx.org/download/nginx-1.8.0.tar.gz
http://wiki.nginx.org/File:Nginx-accesskey-2.0.3.tar.gz
2.安装
[root@test-huanqiu ~]# tar -zxvf nginx-1.8.0.tar.gz
[root@test-huanqiu ~]# cd nginx-1.8.0/
[root@test-huanqiu ~]# tar -xvfz nginx-accesskey-2.0.3.tar.gz
[root@test-huanqiu ~]# cd nginx-accesskey-2.0.3
[root@test-huanqiu nginx-accesskey-2.0.3]# vim config
#替换其中的”$HTTP_ACCESSKEY_MODULE”为”ngx_http_accesskey_module” (这是此模块的一个bug)

接着编译安装nginx
[root@test-huanqiu nginx-1.8.0]# ./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --add-module=/root/nginx-accesskey-2.0.3

配置nginx:
location /download {
    accesskey on;
    accesskey_hashmethod md5;
    accesskey_arg "key";
    accesskey_signature "mypass$remote_addr";
}

配置说明:
accesskey为模块开关;
accesskey_hashmethod为加密方式MD5或者SHA-1;
accesskey_arg为url中的关键字参数;
accesskey_signature为加密值,此处为mypass和访问IP构成的字符串。

编写测试脚本download.php:
<?
$ipkey= md5("mypass".$_SERVER['REMOTE_ADDR']);
$output_add_key="<a href=http://www.wangshibo.com/download/G3200507120520LM.rar?key=".$ipkey.">download_add_key</a><br />";
$output_org_url="<a href=http://www.wangshibo.com/download/G3200507120520LM.rar>download_org_path</a><br />";
echo $output_add_key;
echo $output_org_url;
?>

如上配置后:
访问第一个download_add_key链接可以正常下载,第二个链接download_org_path会返回403 Forbidden错误。

如果不怕麻烦,有条件实现的话,推荐使用第三方模块ngx_http_accesskey_module实现的防盗链。
它的运行方式是:
比如download目录下有一个 file.zip 的文件。对应的URI 是http://www.wangshibo.com/download/file.zip
使用ngx_http_accesskey_module模块后http://www.wangshibo.com/download/file.zip?key=09093abeac094. 只有给定的key值正确了,才能够下载download目录下的file.zip。而且 key 值是根据用户的IP有关的,这样就可以避免被盗链了。
据说Nginx HttpAccessKeyModule现在连迅雷都可以防了,可以尝试一下。

Nginx中防盗链(下载防盗链和图片防盗链)操作记录的更多相关文章

  1. nginx配置图片防盗链

    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)${ expires 30d; access_log off; valid_referers none blocked ...

  2. nginx系统真正有效的图片防盗链完整设置详解

    原文:http://www.wufangbo.com/nginx-fang-dao-lian/ 关于nginx防盗链的方法网上有很多教程,都可以用,但是我发现很多教程并不完整,所做的防盗链并不是真正的 ...

  3. Nginx修改配置实现图片防盗链

    一般情况下,防盗链是针对软件下载和图片的,由于一般的站点不提供资源下载,所以本文主要是针对图片的防盗链 1.如果对全站图片做防盗链,至少需要一个另外的域名存放指向图片.因为如果对全站图片做了防盗链,包 ...

  4. asp.net MVC 网站图片防盗链的几种方法

    目录 1. 通过 URL Rewrite Module 组件 2. 通过 nginx 图片防盗链 3.自定义 HttpHandler 处理 4. 通过 MVC 自定义路由规则防盗链 5. 通过 MVC ...

  5. ASP.NET 实现简单的图片防盗链介绍

    在此,网站图片防盗链的方法是,通过获取Http请求头中的 Referer 标头与本网站域名比较,来判断用户是否来自本站跳转过来的 . 创建一个全局处理程序,用来处理images目录下的图片的直接请求: ...

  6. CSS代码实现图片防盗链

    CSS代码实现图片防盗链的方法其实很简单.在CSS文件中添加以下代码: img { filter:exPRession( this.不能去掉 ? "" : ( (!this.com ...

  7. ASP.NET MVC 利用IRouteHandler, IHttpHandler实现图片防盗链

    你曾经注意过在你服务器请求日志中多了很多对图片资源的请求吗?这可能是有人在他们的网站中盗链了你的图片所致,这会占用你的服务器带宽.下面这种方法可以告诉你如何在ASP.NET MVC中实现一个自定义Ro ...

  8. php如何控制用户对图片的访问 PHP禁止图片盗链(转载)

    把images目录设置成不充许http访问(把图片目录的:读取.目录浏览 两个权限去掉). 用一个PHP文件,直接用file函数读取这个图片.在这个PHP文件里进行权限控制. apache环境中,在你 ...

  9. Asp.Net Core 通过中间件防止图片盗链

    一.原理 要实现防盗链,我们就必须先理解盗链的实现原理,提到防盗链的实现原理就不得不从HTTP协议说起,在HTTP协议中,有一个表头字段叫referer,采用URL的格式来表示从哪儿链接到当前的网页或 ...

随机推荐

  1. Mac键盘图标与对应快捷按键标志汇总

    Mac键盘图标与对应快捷按键 ⌘--Command () win键 ⌃ --Control ctrl键 ⌥--Option (alt) ⇧--Shift ⇪--Caps Lock fn--功能键就是 ...

  2. Android HandlerThread 的使用及其Demo (转)

    转自http://www.cnblogs.com/hnrainll/p/3597246.html 介绍 首先我们来看看为什么我们要使用HandlerThread?在我们的应用程序当中为了实现同时完成多 ...

  3. try it, then you know . Emacs

     原来Emacs能做时间管理 http://sachachua.com/blog/2012/07/transcript-emacs-chat-john-wiegley/ http://blog.csd ...

  4. js中replace的回调函数使用。

    这只是一个小问题,但是之前并没有发现.这个问题就是replace的第二个函数是支持回调函数的. var ext = new RegExp('f','g'); 1.str.replace(ext ,1) ...

  5. jQuery checkbox 所有 全选、全不选、是否选中等

    下面是网络收集: jquery判断checked的三种方法:.attr('checked):   //看版本1.6+返回:”checked”或”undefined” ;1.5-返回:true或fals ...

  6. 语义化HTML

    一.怎样语义化html结构 语义化是指用合理HTML标签以及其特有的属性去格式化文档内容. 正确语义化----结构(html)才是重点,样式(css)是用来修饰结构的.所以要先确定html,确定标签, ...

  7. UIkit框架之UIPickerView

    1.继承链:UIview:UIResponder:NSObject 2.获取uipicker view的属性 (1)@property(nonatomic, readonly) NSIntegernu ...

  8. WebApi:WebApi的Self Host模式

    不用IIS也能執行ASP.NET Web API 转载:http://blog.darkthread.net/post-2013-06-04-self-host-web-api.aspx 在某些情境, ...

  9. CodeBlocks配置pthread环境

    参考资料:MinGW配置pthread环境 按[参考资料]里说的[下载资源]后,将libpthreadGC2.a放到codeBlocks安装目录下的MinGW\lib目录下,然后将pthread.h ...

  10. Java代码规范性

    ---------------------------------------------------------------------------------------------------- ...