Nginx 限制单个IP的并发连接数/速度防止恶意攻击/蜘蛛爬虫采集
博客网站经常被一些竞争对手恶意攻击、或垃圾蜘蛛爬虫采集造成服务器飙升的情况,例如经常性的碰到 YandexBot 、 SMTBot 等等这类不需要的网络蜘蛛爬虫的骚扰,有些甚至一天的采集量达到接近1G的流量,虽然可以通过【使用Fail2ban禁止垃圾采集爬虫,保护Nginx服务器】一文的办法来屏蔽,但是这类爬虫还是会不断变更名字继续出现。
其实,可以使用Nginx限制单个IP的并发连接数能够减少一些采集程序或者DDOS的攻击。
下面是以军哥 LNMP 一键安装包为例的,其他LNMP包自行参考其文档吧。
在LNMP的Nginx配置中已经添加了部分代码,但是是注释掉的,可以编辑/usr/local/nginx/conf/nginx.conf
文件
注明下面的设置需要在 1.1.8以上版本的Nginx 的设置才有效的,至于老版本的我就不在多说了,毕竟还用老版本的真心是不多见了!
查找:
#limit_conn_zone $binary_remote_addr zone=perip:10m;
将前面的#去掉,没这一行的,话加上
limit_conn_zone $binary_remote_addr zone=perip:10m;
默认情况下,如下图所示位置:
再在要设置限制连接数的虚拟主机配置里的server段里添加上
limit_conn perip 10;
10表示单个IP的最大并发连接数。
limit_rate 100k;
limit_rate
为限速为 100KB/秒
。
如下图实例截图:
限制每个连接速度为100K,此限制是针对单个线程,比如,我用IE下载是100K,当用迅雷时它会占用2个线程,所以迅雷下载速度为200K,如果单个IP的并发数设置为10,则多线程下载的话速度可以达到100K×10。
最后运行
/usr/local/nginx/sbin/nginx -t
测试配置是否有错误,如没有错误执行:
/usr/local/nginx/sbin/nginx -s reload
重载配置使其生效。
至此,就完成了 Nginx 限制单个IP的并发连接数/速度来减缓垃圾蜘蛛爬虫采集造成的服务器负载压力了,
当然效果还是要看实际数据采集情况的,会观察一阵子的,感觉原理上应该是有效的!
对单个IP有个基本的限制还是比较靠谱的,毕竟网上太多不受规矩的爬虫了。
Nginx 限制单个IP的并发连接数改进适配开启 CDN 站点
上面介绍的方法,对于那些垃圾爬虫频繁抓取有一定的遏制,但是有一个不足的地方就是在站点开启 CDN 后因为有了 CDN 节点代理的存在,造成屏蔽的IP都是 CDN 节点的IP,误伤率太高了,明显的不科学呀!
在度娘、谷姐了一番后,终于还是找到了有效的办法来应对这个问题了,今天就继续给大家分享一下。
Nginx 有 2 个模块用于控制访问“数量”和“速度”,简单的说,控制你最多同时有多少个访问,并且控制你每秒钟最多访问多少次, 你的同时并发访问不能太多,也不能太快,不然就“杀无赦”。
-
HttpLimitZoneModule
限制同时并发访问的数量 -
HttpLimitReqModule
限制访问数据,每秒内最多几个请求
今天我们要讲的是如何在站点开启了 CDN 后来根据真实IP(非 CDN 节点IP)来限制并发连接和限速。
很多时候,我们的网站不是简单的:普通用户IE浏览器 ——-> 你的服务器 的结构, 考虑到网络访问速度问题,我们中间可能会有各种 网络加速(CDN)。
以我的博客网站 www.mimvp.com 为例,考虑到网站的安全性和访问加速,我们的架构是:
普通用户浏览器
—–> 360网站卫士加速(CDN,360防 CC,DOS攻击)
——> 阿里云加速服务器(我们自己建的CDN,阿里云盾)
—-> 源服务器(PHP 程序部署在这里,iptables, nginx 安全配置)
可以看到,我们的网站中间经历了好几层的透明加速和安全过滤。因为不能基于网站源IP的限制,否则就是把 360网站卫士 或者 阿里云盾 给限制了(CDN加速的IP限制了),因为这里“源IP”地址不再是 真实访问者的IP,而是中间 网络加速服务器 的IP地址。我们需要限制的是 最前面的真实访问者(一般需要限制的都是些垃圾爬虫、XLS扫描、漏洞扫描器等等),而不是中间为我们做加速的 加速服务器。
当一个 CDN 或者透明代理服务器把用户的请求转到后面服务器的时候,这个 CDN 服务器会在 Http 的头中加入 一个记录
X-Forwarded-For:用户IP, 代理服务器IP
如果中间经历了不止一个 代理服务器,像 www.mimvp.com 中间建立多层代理之后,这个 记录会是这样
X-Forwarded-For : 用户IP, 代理服务器1-IP, 代理服务器2-IP, 代理服务器3-IP, ….
可以看到经过好多层代理之后, 用户的真实IP 在第一个位置, 后面会跟一串中间代理服务器的IP地址,从这里取到用户真实的IP地址,针对这个 IP 地址做限制就可以了。
那么具体Nginx的配置里可以通过如下的方式来获取访问者真实IP,而不是中间代理服务器的IP地址:
在nginx.conf的[http]模块里添加如下代码
#获取用户真实IP,并赋值给变量$clientRealIP
map $http_x_forwarded_for $clientRealIp {
"" $remote_addr;
~^(?P<firstAddr>[0-9\.]+),?.*$ $firstAddr;
}
通过 map 指令,我们为 nginx 创建了一个变量 $clientRealIp ,这个就是 原始用户的真实 IP 地址,不论用户是直接访问,还是通过一串 CDN 之后的访问,我们都能取得正确的原始IP地址。
怎么样?很神奇吧,那么具体这个有效与否呢,很简单,利用Nginx的echo来测试一下即可。
在Nginx的站点配置文件里[server]模块里加上下面一段代码:
server {
listen 80;
server_name www.mydomain.com;
#当用户访问 /nginx-test 的时候,我们输出 $clientRealIp 变量,看看这个变量
#值是不是真的 用户源IP 地址
location /nginx-test {
echo $clientRealIp;
}
}
接下来,用你的浏览器访问 www.mydomain.com/nginx-test,这个时候会弹出框下载一个文件 nginx-test,下载完成用 notepad++ 打开,里面就是一个 IP 地址,访问 www.ipip.net ,看看这个里面记录的IP地址是否和 ip 侦测的IP 一致?
通过这种方式,你就可以对 Nginx 的一些复杂配置做有效的测试。
经过测试,我们确认 通过多层CDN 之后,$clientRealIp 仍然是有效的原始用户IP地址。
下面就可以根据上述所获得的 用户真实 IP 做连接限制了:
在nginx.conf的[http]模块里添加如下代码
#用户的 IP 地址 $clientRealIP 作为 Key,每个 IP 地址最多有 20 个并发连接
#你想开几千个连接刷死我? 超过 20 个连接,直接返回 503 错误给你,根本不处理你的请求了
limit_conn_zone $clientRealIP zone=TotalConnLimitZone:10m ;
limit_conn TotalConnLimitZone 20;
limit_conn_log_level notice;
#用户的 IP 地址 $clientRealIP 作为 Key,每个 IP 地址每秒处理 10 个请求
#你想用程序每秒几百次的刷我,没戏,再快了就不处理了,直接返回 503 错误给你
limit_req_zone $clientRealIP zone=ConnLimitZone:10m rate=10r/s;
limit_req_log_level notice;
最后在Nginx的站点配置文件里[server]模块里加上下面一段代码:
limit_req zone=ConnLimitZone burst=5 nodelay;
这样限制单个真实访客IP并发连接数以及速度限制就生效了,实现的效果是:“ 最多 5 个排队, 由于每秒处理 10 个请求 + 5个排队,你一秒最多发送 15 个请求过来,再多就直接返回 503 错误给你了”
好了,今天分享这个方法,自己是已经在我所有的站点下都测试部署成功并生效了,上述Nginx配置代码大家只要简单的修改一下甚至可以直接复制粘贴就可以使用了,只是每段代码大家要搞清楚具体放到哪里,放错位置可是会造成Nginx重启失效的,所以大家每次修改了对应的conf
文件后记得要nginx -t
让Nginx检查一下配置文件是否有错误,以免造成服务器宕机的风险。
原文:Nginx 限制单个IP的并发连接数/速度来减缓垃圾蜘蛛爬虫采集 (明月登楼博客)
版权所有: 本文系米扑博客原创、转载、摘录,或修订后发表,最后更新于 2018-10-11 05:24:19
侵权处理: 本个人博客,不盈利,若侵犯了您的作品权,请联系博主删除,莫恶意,索钱财,感谢!
多谢分享。