听说你的资源被盗用了,那你知道 Nginx 怎么防盗链吗?
上一篇文章讲了 Nginx 中的变量和运行原理,下面就来说一个主要提供变量并修改变量的值的模块,也就是我们要讲的防盗链模块:referer 模块。
简单有效的防盗链手段
场景
如果做过个人站点的同学,可能会遇到别人盗用自己站点资源链接的情况,这就是盗链。说到盗链就要说一个 HTTP 协议的 头部,referer 头部。当其他网站通过 URL 引用了你的页面,用户在浏览器上点击 URL 时,HTTP 请求的头部会通过 referer 头部将该网站当前页面的 URL 带上,告诉服务器本次请求是由谁发起的。
例如,在谷歌中搜索 Nginx 然后点击链接:
在打开的新页面中查看请求头会发现,请求头中包含了 referer 头部且值是 https://www.google.com/。
像谷歌这种我们是允许的,但是有一些其他的网站想要引用我们自己网站的资源时,就需要做一些管控了,不然岂不是谁都可以拿到链接。
目的
这里目的其实已经很明确了,就是要拒绝非正常的网站访问我们站点的资源。
思路
- invalid_referer 变量
- referer 提供了这个变量,可以用来配置哪些 referer 头部合法,也就是,你允许哪些网站引用你的资源。
referer 模块
要实现上面的目的,referer 模块可得算头一号,一起看下 referer 模块怎么用的。
- 默认编译进 Nginx,通过
--without-http_referer_module
禁用
referer 模块有三个指令,下面看一下。
Syntax: valid_referers none | blocked | server_names | string ...;
Default: —
Context: server, location
Syntax: referer_hash_bucket_size size;
Default: referer_hash_bucket_size 64;
Context: server, location
Syntax: referer_hash_max_size size;
Default: referer_hash_max_size 2048;
Context: server, location
valid_referers
指令,配置是否允许 referer 头部以及允许哪些 referer 访问。referer_hash_bucket_size
表示这些配置的值是放在哈希表中的,指定哈希表的大小。referer_hash_max_size
则表示哈希表的最大大小是多大。
这里面最重要的是 valid_referers
指令,需要重点来说明一下。
valid_referers 指令
可以同时携带多个参数,表示多个 referer 头部都生效。
参数值
- none
- 允许缺失 referer 头部的请求访问
- block:允许 referer 头部没有对应的值的请求访问。例如可能经过了反向代理或者防火墙
- server_names:若 referer 中站点域名与 server_name 中本机域名某个匹配,则允许该请求访问
- string:表示域名及 URL 的字符串,对域名可在前缀或者后缀中含有 * 通配符,若 referer 头部的值匹配字符串后,则允许访问
- 正则表达式:若 referer 头部的值匹配上了正则,就允许访问
invalid_referer 变量
- 允许访问时变量值为空
- 不允许访问时变量值为 1
实战
下面来看一个配置文件。
server {
server_name referer.ziyang.com;
listen 80;
error_log logs/myerror.log debug;
root html;
location /{
valid_referers none blocked server_names
*.ziyang.com www.ziyang.org.cn/nginx/
~\.google\.;
if ($invalid_referer) {
return 403;
}
return 200 'valid\n';
}
}
那么对于这个配置文件而言,以下哪些请求会被拒绝呢?
curl -H 'referer: http://www.ziyang.org.cn/ttt' referer.ziyang.com/
curl -H 'referer: http://www.ziyang.com/ttt' referer.ziyang.com/
curl -H 'referer: ' referer.ziyang.com/
curl referer.ziyang.com/
curl -H 'referer: http://www.ziyang.com' referer.ziyang.com/
curl -H 'referer: http://referer.ziyang.com' referer.ziyang.com/
curl -H 'referer: http://image.baidu.com/search/detail' referer.ziyang.com/
curl -H 'referer: http://image.google.com/search/detail' referer.ziyang.com/
我们需要先来解析一下这个配置文件。valid_referers
指令配置了哪些值呢?
valid_referers none blocked server_names
*.ziyang.com www.ziyang.org.cn/nginx/
~\.google\.;
- none:表示没有 referer 的可以访问
- blocked:表示 referer 没有值的可以访问
- server_names:表示本机 server_name 也就是 referer.ziyang.com 可以访问
- *.ziyang.com:匹配上了正则的可以访问
- www.ziyang.org.cn/nginx/:该页面发起的请求可以访问
- ~\.google\.:google 前后都是正则匹配
下面就实际看下响应:
# 返回 403,没有匹配到任何规则
➜ ~ curl -H 'referer: http://www.ziyang.org.cn/ttt' referer.ziyang.com/
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.17.8</center>
</body>
</html>
➜ ~ curl -H 'referer: http://image.baidu.com/search/detail' referer.ziyang.com/
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.17.8</center>
</body>
</html>
# 匹配到了 *.ziyang.com
➜ ~ curl -H 'referer: http://www.ziyang.com/ttt' referer.ziyang.com/
valid
➜ ~ curl -H 'referer: http://www.ziyang.com' referer.ziyang.com/
valid
# 匹配到了 server name
➜ ~ curl -H 'referer: http://referer.ziyang.com' referer.ziyang.com/
valid
# 匹配到了 blocked
➜ ~ curl -H 'referer: ' referer.ziyang.com/
valid
# 匹配到了 none
➜ ~ curl referer.ziyang.com/
valid
# 匹配到了 ~\.google\.
➜ ~ curl -H 'referer: http://image.google.com/search/detail' referer.ziyang.com/
valid
防盗链另外一种解决方案:secure_link 模块
referer 模块是一种简单的防盗链手段,必须依赖浏览器发起请求才会有效,如果攻击者伪造 referer 头部的话,这种方式就失效了。
secure_link 模块是另外一种解决的方案。
它的主要原理是,通过验证 URL 中哈希值的方式防盗链。
基本过程是这个样子的:
- 由服务器(可以是 Nginx,也可以是其他 Web 服务器)生成加密的安全链接 URL,返回给客户端
- 客户端使用安全 URL 访问 Nginx,由 Nginx 的 secure_link 变量验证是否通过
原理如下:
- 哈希算法是不可逆的
- 客户端只能拿到执行过哈希算法的 URL
- 仅生成 URL 的服务器,验证 URL 是否安全的 Nginx,这两者才保存原始的字符串
- 原始字符串通常由以下部分有序组成:
- 资源位置。如 HTTP 中指定资源的 URI,防止攻击者拿到一个安全 URI 后可以访问任意资源
- 用户信息。如用户的 IP 地址,限制其他用户盗用 URL
- 时间戳。使安全 URL 及时过期
- 密钥。仅服务器端拥有,增加攻击者猜测出原始字符串的难度
模块:
- ngx_http_secure_link_module
- 未编译进 Nginx,需要通过 --with-http_secure_link_module 添加
- 变量
- secure_link
- secure_link_expires
Syntax: secure_link expression;
Default: —
Context: http, server, location
Syntax: secure_link_md5 expression;
Default: —
Context: http, server, location
Syntax: secure_link_secret word;
Default: —
Context: location
变量值及带过期时间的配置示例
- secure_link
- 值为空字符串:验证不通过
- 值为 0:URL 过期
- 值为 1:验证通过
- secure_link_expires
- 时间戳的值
命令行生成安全链接
- 生成 md5
echo -n '时间戳URL客户端IP密钥' | openssl md5 -binary | openssl base64 | tr +/ - | tr -d =
- 构造请求 URL
/test1.txt?md5=md5生成值&expires=时间戳(如 2147483647)
Nginx 配置
- secure_link $arg_md5,$arg_expires;
- secure_link 后面必须跟两个值,一个是参数中的 md5,一个是时间戳
- secure_link_md5 "$secure_link_expires$uri$remote_addr secret";
- 按照什么样的顺序构造原始字符串
实战
下面是一个实际的配置文件,我这里就不做演示了,感兴趣的可以自己做下实验。
server {
server_name securelink.ziyang.com;
listen 80;
error_log logs/myerror.log info;
default_type text/plain;
location /{
secure_link $arg_md5,$arg_expires;
secure_link_md5 "$secure_link_expires$uri$remote_addr secret";
if ($secure_link = "") {
return 403;
}
if ($secure_link = "0") {
return 410;
}
return 200 '$secure_link:$secure_link_expires\n';
}
location /p/ {
secure_link_secret mysecret2;
if ($secure_link = "") {
return 403;
}
rewrite ^ /secure/$secure_link;
}
location /secure/ {
alias html/;
internal;
}
}
仅对 URI 进行哈希的简单办法
除了上面这种相对复杂的方式防盗链,还有一种相对简单的防盗链方式,就是只对 URI 进行哈希,这样当 URI 传
- 将请求 URL 分为三个部分:/prefix/hash/link
- Hash 生成方式:对 “link 密钥” 做 md5 哈希
- 用
secure_link_secret secret;
配置密钥
命令行生成安全链接
- 原请求
- link
- 生成的安全请求
- /prefix/md5/link
- 生成 md5
echo -n 'linksecret' | openssl md5 –hex
Nginx 配置
secure_link_secret secret;
这个防盗链的方法比较简单,那么具体是怎么用呢?大家都在网上下载过资源对吧,不管是电子书还是软件,很多网站你点击下载的时候往往会弹出另外一个页面去下载,这个新的页面其实就是请求的 Nginx 生成的安全 URL。如果这个 URL 被拿到的话,其实还是可以用的,所以需要经常的更新密钥来确保 URL 不会被盗用。
今天这篇文章详细讲了防盗链的具体用法,最近的这两篇文章都是说的已有的变量用法,下一篇文章讲一下怎么生成新的变量。
本文首发于我的个人博客:iziyang.github.io,所有配置文件我已经放在了 Nginx 配置文件,大家可以自取。
听说你的资源被盗用了,那你知道 Nginx 怎么防盗链吗?的更多相关文章
- 网站资源被盗链的:预防方法 VS 网站资源防盗链的:破解技巧
1 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问! 1 资源被盗链:(简明定义) 下载者不是从你的网站直接下载资源,而是通过其他盗链网站提供的你的下载资源链接进行下载你的服务 ...
- Nginx实践篇(2)- Nginx作为静态资源web服务 - 控制浏览器缓存、防盗链
一.控制浏览器缓存 1. 浏览器缓存简介 浏览器缓存遵循HTTP协议定义的缓存机制(如:Expires;Cache-control等). 当浏览器无缓存时,请求响应流程 当浏览器有缓存时,请求响应流程 ...
- nginx实践(四)之静态资源web服务(防盗链)
防盗链目的 防止资源被盗用 http_refer 主要是判断refer信息,判断请求来源是不是合法身份 语法 实例 参数说明: none表示允许没有代理的头信息过来,blocked表示refer信息不 ...
- Nginx作为静态资源web服务之防盗链
Nginx作为静态资源web服务之防盗链 首先,为什么需要防盗链,因为有些资源存在竞争对手的关系,比如淘宝的商品图片,不会轻易的让工具来爬虫爬走收集.但是如果使用防盗链,需要知道上一个访问的资源,然后 ...
- Nginx作为web静态资源服务器——防盗链
基于http_refer防盗链配置模块 Syntax:valid_referers none | blocked | server_names | string ...; Default:—— C ...
- Nginx 配置静态资源防盗链
# 什么是静态资源盗链: # 你服务器上的一张图片,127.0.0.1/images/a.png # 别人的html页面可以直接通过<img src="127.0.0.1/images ...
- [日常] 前端资源测试机上忽略版本号的的nginx配置
利用nginx的rewrite的指令,可以实现url的重新跳转,rewrtie有四种不同的flag,分别是redirect(临时重定向).permanent(永久重定向).break和last.其中前 ...
- nginx静态资源防盗链
含义: 用于阻止 Referer 头字段为无效值的请求访问站点.需记住的是,使用适当的 Referer 字段值来伪造请求非常容易,因此本模块的预期目的不是要彻底阻止此类请求,而是阻止常规浏览器发送的大 ...
- cdn加速对门户网站产生的影响
满意的用户体验是门户网站吸引和留住用户的必备条件.据统计,如果等待网页打开的时间超过8秒,将会有超过30%的用户放弃等待,造成严重的用户流失,降低了用户的体验度和忠诚度.门户网站内容涉及面多,涵盖文字 ...
随机推荐
- Lightoj1356
题目链接:https://vjudge.net/problem/LightOJ-1356 题目大意: T个 test case,每个 test case 给出一个 N 个数的集合.请找出一个最大的子集 ...
- 【Oracle】CentOS7/CentOS8命令行重启Oracle 11G R2
写在前面 按照读者朋友的要求写了一篇<[Oracle]CentOS7/CentOS8命令行安装Oracle 11G R2>,由于读者完全是按照我的安装方式安装的Oracle数据库,也是将O ...
- MyBatis中的命名空间namespace的作用
1.定义mapper接口,面向接口编程. 2.在大型项目中,可能存在大量的SQL语句,这时候为每个SQL语句起一个唯一的标识(ID)就变得并不容易了.为了解决这个问题,在MyBatis中,可以为每个映 ...
- JavaScript的流程控制语句以及函数
一.流程控制 1. 作用:控制代码的执行顺序 2. 分类 2.1顺序结构:从上到下依次执行代码语句 2.2选择结构: 1. if语句 简单if结构 if(条件表达式){ 表达式成立时执行的代码段 } ...
- Qt版本中国象棋开发(二)
实现功能:棋盘绘制 核心函数: void paintEvent(QPaintEvent *); //QWidget自带的虚函数,重写后使用 QPainter 类来绘制图形 QPainter paint ...
- Chisel3 - model - IO ports
https://mp.weixin.qq.com/s/fgCvIFt0RdEajhJVSy125w 介绍模块的输入输出端口的定义与管理. 1. _ports 1) 模块的输入输出端口, ...
- 【HBase】rowkey、索引表设计
总订单数1亿条 ->订单id,用户id,商品id集合,订单时间,订单完成时间,订单状态: HBase表设计: 主表 -> Rowkey: 用户ID_时间戳 列簇:info 索引表 -> ...
- 【Linux】将javaweb项目部署到CentOS的tomcat上
1.将项目打包成war包 build之后war文件就生成了. 2.拷贝war文件到CentOS的tomcat的项目文件夹中 用WinSCP将文件粘帖进这个文件夹中 /wocloud/tomcat_cl ...
- 蓝桥杯 算法提高 11-1实现strcmp函数 (JAVA方法)
蓝桥杯 算法提高 11-1实现strcmp函数 (JAVA方法) 首先这不是一个多难的题,但是网上的我没怎么找到有Java的代码,基本全都是c语言的,小编是个小白,如果有不对的地方请联系小编 问题描述 ...
- Java实现 LeetCode 766 托普利茨矩阵(暴力)
766. 托普利茨矩阵 如果一个矩阵的每一方向由左上到右下的对角线上具有相同元素,那么这个矩阵是托普利茨矩阵. 给定一个 M x N 的矩阵,当且仅当它是托普利茨矩阵时返回 True. 示例 1: 输 ...