场景:有一tengine的反向代理,主要反向代理到几个后端服务器上,后端服务器提供数千万的图片文件,众所周知的原因,图片是很容易被盗链的,而使用refer来反盗链的话,一是可以伪造refer,另一个是 众多合作网站需要来调用图片,需要手动添加refer,因此决定使用nginx_accesskey模块来实现。
1 tengine中新增nginx_accesskey模块。
不得不说tengine的DSO功能真的很爽,如果一个线上的服务器需要新增个模块进来的话,为了减少重编译nginx,采用Tengine来操作 可以将模块直接编译成.so动态加载给nginx。
<code> </code><code>wget http:</code><code>//wiki</code><code>.nginx.org</code><code>/images/5/51/Nginx-accesskey-2</code><code>.0.3.</code><code>tar</code><code>.gz</code>
<code> </code><code>tar</code> <code>-zxvf Nginx-accesskey-2.0.3.</code><code>tar</code><code>.gz </code>
<code> </code><code>cd</code> <code>nginx-accesskey-2.0.3/</code>
<code> </code><code>vim config</code>
<code>修改$HTTP_ACCESSKEY_MODULE为ngx_http_accesskey_module</code>
<code> </code><code>cd</code> <code>/usr/local/cloud/nginx/tengine2</code><code>.0.0</code><code>/sbin</code>
<code> </code><code>.</code><code>/dso_tool</code> <code>--add-module=</code><code>/home/skybug/nginx-accesskey-2</code><code>.0.3 --dst=</code><code>/usr/local/vipcloud/nginx/dso/</code>
至此,将ngx_http_accesskey_module.so编译并复制到了 tengine的dso目录下。
修改nginx.conf
添加 lodad ngx_http_accesskey_module.so;
ngx_http_accesskey变动态加载到tengine中。
2 如何使用ngx_http_accesskey 实现防盗链
在server段的某一个location中添加如下:
比如
<code>location ~*\.(gif)$</code>
<code> </code><code>{</code>
<code> </code><code>root </code><code>/var/www/image</code><code>.xxx.com;</code>
<code> </code><code>access_log off;</code>
<code> </code><code>expires 7d;</code>
<code> </code><code>accesskey on;</code>
<code> </code><code>accesskey_hashmethod md5;</code>
<code> </code><code>accesskey_arg </code><code>"key"</code><code>;</code>
<code> </code><code>accesskey_signature </code><code>"dasiyebushuo$remote_addr"</code><code>;</code>
<code>}</code>
这个时候 如果你访问
http://image.xxx.com/mmm/nnn/test.gif
会看到 报出403错误 没有权限访问。
如何正常来访问这个图片呢?
如果某一个客户的ip地址是 192.168.0.1
那么 dasiyebushuo192.168.0.1的md5为b49eeb993eaf25edfeca43bdaf07c541
正常访问这个图片的方法是
http://image.xxx.com/mmm/nnn/test.gif?key=b49eeb993eaf25edfeca43bdaf07c541
页面里调用图片的方法 只需要把dasiyebushuo$remoteip 计算一下md5然后作为key的参数来访问即可,
说明:
accesskey on; 是否启用accesskey 防盗链
accesskey_hashmethod md5; 采用md5来hash参数,可以选hash或md5
accesskey_arg "key";参数名,如果你设置为site 那么就是xxx.gif?site= 如果设置为key 就是xxx.gif?key=
accesskey_signature "dasiyebushuo$remote_addr"; 具体用什么来hash 可以是客户IP 可以是cookie nginx的内置变量均可,通常采用remote_addr,也可以用cookie来hash;dasiyebushuo 扰乱用的,如果你用客户iphash 别人也可以吧客户的iphash出来提交就渠道图片了,如果你在客户的ip前面加一个串一起来hash 除非别人猜出来用的什么
3 在http_proxy 反向代理中如何使用ngx_http_accesskey_module
nginx的三方模块很多,但是想让这些模块都一起来配合工作就不一定了。比如如果你的nginx是一个反向代理的图片前端服务器,采用nginx-accesskey 后比如配置为
location ~*\.(gif)$
{
expires 7d;
accesskey on;
accesskey_hashmethod md5;
accesskey_arg "site";
accesskey_signature "dasiyebushuo$remote_addr";
proxy_cache_valid 200 304 5d;
proxy_cache_valid 301 302 30m;
proxy_cache_valid any 30m;
proxy_cache_key $host$uri$is_args$args;
proxy_set_header Host pic1.xxxx.com;
proxy_set_header X-forwarded-For $remote_addr;
proxy_pass http://pic.xxxx.com_server_pool;
}
我们以为这样就可以了,结果发现 在访问图片的时候,无论你加不加?site=b49eeb993eaf25edfeca43bdaf07c541 图片都出的来, accesskey 完全没有起作用。非常郁闷。
nginx有个神奇的功能 404重定向,ok 思路换一下,先让我们到本地去找文件(由于是反向代理,实际上任何访问的图片都不在nginx上 而是在后端服务器上,那么只有1种情况,就是访问会返回404,利用accesskey模块先来验证用户的请求对不对,如果没有加?site==b49eeb993eaf25edfeca43bdaf07c541或者 ?site=md5(dasiyebushuo$remote_addr)传入的不对,恩 是盗链 则直接返回403!如果是对了呢?对了就去/var/www/给你找这个文件,当然了,找不到赛,因此是个404,我们把404直接定向到@fallback这一段去处理。
然后在@fallback这段里 我们直接proxy_pass到后端去。修改后的配置如下:
<code> </code><code>root </code><code>/var/www/</code><code>;</code>
<code> </code><code>accesskey_arg </code><code>"site"</code><code>;</code>
<code> </code><code>error_page 404 = @fallback;</code>
<code>location @fallback {</code>
<code> </code><code>proxy_cache_valid 200 304 5d;</code>
<code> </code><code>proxy_cache_valid 301 302 30m;</code>
<code> </code><code>proxy_cache_valid any 30m;</code>
<code> </code><code>proxy_cache_key $host$uri$is_args$args;</code>
<code> </code><code>proxy_set_header Host pic1.xxxx.com;</code>
<code> </code><code>proxy_set_header X-forwarded-For $remote_addr;</code>
<code> </code><code>proxy_pass http:</code><code>//pic</code><code>.xxxx.com_server_pool;</code>
测试后发现这样可行
本文转自天山三害 51CTO博客,原文链接:http://blog.51cto.com/skybug/1630732,如需转载请自行联系原作者