爬虫与反爬虫的较量:如何与恶意爬虫做斗争?

👨‍💻罗格 💠计算机服务器操作指南 ⏰6年前 (2018-06-29) 👁️8722 Views 💬4 comments
!本文可能 超过2年没有更新,今后内容也许不会被维护或者支持,部分内容可能具有时效性,涉及技术细节或者软件使用方面,本文不保证相应的技术更新和实践可操作性。
文章目录[隐藏]

如何与恶意爬虫做斗争?

这篇文章我将归类到技术文档里,早前接触过爬虫因为我并不是什么技术栈,所以写的东西都比较粗陋,以前用过别人的爬虫拿来简单的练手,但是一般都会去人家网站点击几个广告,毕竟爬了人家的站,大家都是站长,明白这中间的不容易,因为网上拿来的爬虫大多数是别人写好的,我懂得不多,所以只是简单的测试玩玩,现在我手里好多网站都是基于Typecho开发或者二开,最近在你好污啊进行了扩展,新增了模块心灵毒鸡汤,为了引流就在V2ex发布了一下,然而从发布到本文起稿时,网站已经瘫痪,没有猜错,是有人在用爬虫不断的请求,导致资源被榨干,一直抛出502状态,因此导致新访客也无法访问。

nginx日志爬虫记录

那么如何区分访问者与恶意爬虫呢?我们分析上图可以看到首先对方频率很高,每秒执行的请求次数过高,其次每次请求头Header都没做处理显示的是 Python/3.6 这个只是本站的爬虫,大多数时候Header并不能作为判断依据,因为这个很容易伪造,再次我们看访问响应,可以看到该请求因为频率过高导致服务器瘫痪,其爬虫本身就收到无数的502状态,但是还在访问,这么基本可以断定不是访问者了,正常访问者在请求响应是502的状态看到的只是错误页面,最多刷新几次就会跳出,而这里的因为是爬虫,所以即使出错也会一直请求,当然这是一只不太人性化的爬虫,如果通过机器学习完全模拟人工频率那我们也就很难来控制了,但是爬虫到那个地步对网站影响已经不大了。

因为心灵毒鸡汤上线时间短,中途我休息了2个小时左右,才让爬虫有机可乘,我向来不反对大家对于心灵毒鸡汤包括你好污啊主站的爬取,本来作为公开的信息,在互联网化的环境,人人可取,但是这个爬虫比较恶劣,不做频率处理,直接导致网站崩溃,所以我直接封禁了IP。

使用命令查看日志中访问次数最多50个ip,然后对访问次数超常的IP采取措施,查看访问次数最多的IP的命令如下:

awk '{print $1}' /home/wwwlogs/www.nihaowua.com.log | sort|uniq -c | sort -nr | head -n 50

我们大多数人用的都是LNMP环境,那么Nginx服务器如何屏蔽指定IP呢,这里以我本地军哥LNMP为例,首先进入到 /usr/local/nginx/conf 目录,在该目录下新增 blockip.conf 配置文件,在 blockip.conf 中写入需要封禁的IP,写法如下:

deny 118.24.19.90; 
deny 61.190.32.52;

#nginx封禁IP段
deny 123.0.0.0/8;# 屏蔽整个段即从123.0.0.1到123.255.255.254访问的命令
deny 124.45.0.0/16;# 屏蔽IP段即从123.45.0.1到123.45.255.254访问的命令
deny 123.45.6.0/24;# 屏蔽IP段即从123.45.6.1到123.45.6.254访问的命令

deny表示屏蔽该地址,后面直接跟上你要屏蔽的IP即可,然后打开你的网站nginx配置文件,通常目录是 /usr/local/nginx/conf/domain.com/ 这里的domain.com是你的域名,修改该目录下的conf配置文件,在server段中写入刚才我们配置的blockip.conf,写法如下:

#IP地址屏蔽
include blockip.conf;

然后保存配置文件,并重启nginx服务,命令为 lnmp nginx restart 或者 lnmp nginx reload,至此,我们就完成了屏蔽非法IP的基本操作,后期有新的非法IP,直接写入到 blockip.conf 配置文件即可,记得每次修改 blockip.conf 文件以后都要重启 nginx 服务才能生效。

20180630更新:截止本日发现非法IP依然在请求,虽然通过Nginx屏蔽了IP,但是该IP在请求状态为403的时候依然不依不饶,看着逐渐增大的nginx日志文件,强迫症又犯了,直接在iptables里干掉了这个ip,命令操作方式如下:

iptables -I INPUT -s 211.1.0.0 -j DROP

#查看iptables命令
iptables -L -n

#解封iptables某个屏蔽的IP
iptables -D INPUT -s 211.1.0.0 -j REJECT 

也许上面的做法你觉得依然不够人性化,因为你不可能一直盯着nginx日志去观察这些非法IP,那么这时候该怎么操作呢?继续往下看。

反爬虫进阶手段:

我们通过上面的图片其实可以看出爬虫的几个基本通性就是模拟请求,模拟请求就会涉及到访问频率,频率,时长,请求头等一些因素,一个正常人工操作是不可能每秒请求网站很多次,也不可能一天24小时都在请求,他的请求头通常不应该是python,当他请求出错了以后不可能一直继续请求下去。所以我们设定一个阈值每分钟访问次数超过80次即判断为爬虫,这里的阈值需要大家根据具体情况设置,我们要做的就是写一个Nginx监控脚本,当网站请求达到阈值时我们就执行发送邮件给管理员,这样来做到对网站的自动化管理。

备注:本文操作是在日志文件比较小的情况下的操作,如果日志文件每天达到G的量级,或者百兆的量级都不建议使用本文的操作,因为日志文件太大读取起来就比较耗时了,针对日志文件较大的情况请选择专业工具,或者通过sed读取然后将日志存入数据库,程序从数据库中读取分析。

如果你们的系统比较大,做了分布式,访问量也很大,建议你使用ELK(ElasticSearch, Logstash, Kibana)搭建实时日志分析平台。

以下操作需要服务安装有Python,没有安装的请自行安装。

1、监控Nginx日志

该脚本主要用来监控Nignx产生的日志,看是否有异常IP活动,脚本如下:

[root@nonamedaohao4ma ~]# cat /home/nginx_log_monit.sh
#!/bin/bash
#日志文件
logfile=/home/wwwlogs/nginx/www.nihaowua.com.log
   
#开始时间
start_time=`date -d"$last_minutes minutes ago" +"%H:%M:%S"`
   
#结束时间
stop_time=`date +"%H:%M:%S"`
   
#过滤出单位之间内的日志并统计最高ip数
tac $logfile | awk -v st="$start_time" -v et="$stop_time" '{t=substr($4,RSTART+14,21);if(t>=st && t<=et) {print $0}}' \
| awk '{print $1}' | sort | uniq -c | sort -nr > /home/log_ip_top10
ip_top=`cat /home/log_ip_top10 | head -1 | awk '{print $1}'`
# 单位时间[1分钟]内单ip访问次数超过80次,则触发邮件报警
if [[ $ip_top -gt 80 ]];then
 /usr/bin/python /home/send_mail.py &
fi

2、python报警脚本

监控到非法IP访问即报警给管理员发送邮件

[root@nonamedaohao4ma ~]# cat /home/send_mail.py
# -*- coding: utf-8 -*-
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from datetime import datetime
import os
import smtplib
def _format_addr(s):
 name, addr = parseaddr(s)
 return formataddr((Header(name, 'utf-8').encode(), addr))
# 邮箱定义
smtp_server = 'smtp.exmail.qq.com'
smtp_port = 465
from_addr = '[email protected]'
#这里的密码是邮箱客户端专属密码不是邮箱密码
#这里的密码注意安全,最好的做法是写入系统环境变量
#写入环境变量的代码是 export EMAILPWD=xxxxxx
#调用方式改成 password = os.environ.get('EMAILPWD')
#password = 'xxxxxxxx'
password = os.environ.get('EMAILPWD')
to_addr = ['[email protected]']
# 邮件对象
msg = MIMEMultipart()
msg['From'] = _format_addr('发件人 <%s>' % from_addr)
msg['To'] = _format_addr('收件人 <%s>' % to_addr)
msg['Subject'] = Header('Warning:单ip请求次数异常', 'utf-8').encode()
# 获取系统中要发送的文本内容
with open('/home/log_ip_top10', 'r') as f:
  line = f.readline().strip()
  line = line.split(" ")
print(line)
# 邮件正文是MIMEText:
html = '<html><body><h2>一分钟内单ip请求次数超过阀值</h2>' + \
 '<p>ip:%s  请求次数/min:%s</p>' % (line[1],line[0]) + \
 '</body></html>'

msg.attach(MIMEText(html, 'html', 'utf-8'))
server = smtplib.SMTP_SSL(smtp_server, smtp_port)
server.login(from_addr, password)
server.sendmail(from_addr, to_addr, msg.as_string())
server.quit()

我在昨天测试该段代码使用的QQ企业邮箱,一直报错535,后来网上咨询发现大家的解决办法是给邮箱开通安全登陆生成客户端专属密码才测试通过。另外163邮箱也是一样,需要开通安全登陆并配置客户端专属密码,上面的密码也就是专属密码。

3、脚本警报触发测试

[root@nonamedaohao4ma ~]# cat /home/curl.sh
#!/bin/bash
#example:curl.sh https://www.nihaowua.com 100
usage()
{
 echo "usage: `basename $0` url count"
}
if [ $# -ne 2 ]; then
 usage
 exit 1
fi
for i in `seq 1 $2`;do
 http_code=`curl -o /dev/null -s -w %{http_code} $1`
 echo $1 $http_code
done

手动执行测试脚本

[root@nonamedaohao4ma ~]# /bin/bash /home/curl.sh https://www.nihaowua.com 300

4、加入定时任务

因为我们本次主要是监控用户IP一分钟的活动情况,所以需要给脚本新增每分钟执行一次

[root@nonamedaohao4ma ~]# crontab -e
* * * * * /bin/bash -x /home/nginx_log_monit.sh >/dev/null 2>&1

如果测试时没有收到邮件请检查定时任务日志查看是否成功:tail -f /var/log/cron

5、测试最终结果

shell nginx 邮箱反馈结果

以上就是无人值守自动IP监控的部分代码了,截止到本文完稿时,我发现还有非法IP在不停的请求,然而他只能请求到403。

本文也仅仅是实现了邮件报警功能,实际上还可以通过直接将非法ip写到我们上面新增的 blockip.conf 文件中来实现无人值守自动屏蔽恶意访问的ip或者也可以通过Linux系统防火墙iptables来屏蔽("iptables -I INPUT -s x.x.x.x -j DROP"方式)。

昨晚查看文档发现还有另外两种做法,一种做法是通过ipset来封禁非法IP,相对来说比直接iptables要人性化一些,第二种做法是给ngin安装模块ngx_http_limit_conn_module来屏蔽非法IP请求,该模块主要用来限制每秒请求数量,至于依据什么条件限制是由我们来自定义的,具体的大家可以参考网络文章nginx限制请求数ngx_http_limit_req_module模块

后记:本文没有谈到代理池的问题,因为对方真的想爬你的站,总是会有方法的,这个无法从源头控制非法者,只能通过简单的识别来过滤一些简单的非法访问者,对于代理池简单的监控就是判断一段时间不同IP的活动规律,如果一段时间内的IP访问都是有规律的,并且跳出率为100%,通常可以判定为爬虫,但是问题是我们作为站长是结果处理,当我们能判断结果时,爬虫已经完成了一次爬取,获得了数据并更换IP请求,这个就是成本控制的问题了,你的内容价值高,对方就会愿意去不断修改爬虫获取内容。

最后还是那句话,不反对采集,但是反对非法的榨干资源请求。

特别优惠:免费赠送 $50 Vultr主机-限时优惠!Adsense英文站必备海外服务器!点击了解更多

关注公众号:多思多金,学习更多技巧
喜欢我们吗? 订阅我的博客更新,让你不错过任何帖子。订阅后可以免费获得我正在写的2019年网络赚钱新思路电子书,了解2019年为您的网站带来流量最有效方法

100%的隐私,我和你一样讨厌垃圾邮件!

  • 本文编辑:罗格
  • 本文链接:https://moidea.info/archives/the-contest-between-reptiles-and-anti-reptiles-how-to-fight-against-malicious-reptiles.html
  • 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!
  • 客官,说两句吧!

    已有 4 条评论

    1. 小彦

      嘿嘿,同行!我也很讨厌爬虫,你主要是通过访问频率识别爬虫,然后禁止ip,学习了。我也有一种办法,和你互补,我是通过前端判断是不是人类操作,然后把user agent记录下来?但我发现这么做有缺点,user agent很容易换掉,我看来还是要禁ip了。不过ip也有局限,很多家庭宽带,ip一直在变的~估计两种结合来用比较好~

      1. 罗格
        罗格 管理员 收录情况
        回复

        @小彦 ADSL拨号的暂时没有办法,要么就是服务端直接追踪获得对方MAC地址然后屏蔽,user agent这个很容易伪造,基本上没什么作用,对于高成本的爬虫我一般不去管它,而且爬虫写的越好的作者素质就会越高

        1. hysteria

          @罗格 确实,技术高的技术人员素质很高.相比职校的二流子码农要高尚太多~

          1. 罗格
            罗格 管理员 收录情况

            @hysteria 是的,我觉得采集可以有,但是基本的站长素养也还是要有的