脚本代码参考:https://blog.51cto.com/tsoagta/1710421
我们公司网站爬虫爬取频次太高,查阅资料后简单写了一个定时获取ip,然后封禁ip 的脚本。
主要思路是:读取nginx的access.log 获取ip访问信息,将访问超过多少次的ip存入到blockip.conf,由nginx.conf引用blockip.conf达到封ip目的。
脚本代码新手小白一个,公司没有liunx运维,只能自己查资料上了,文章可能有诸多不足,只为记录分享,看到的朋友请谅解。
1、liunx 执行下面红色字体命令,可查看ip访问信息
awk '{print $1}' /usr/local/nginx/logs/access.log |sort |uniq -c|sort -n
执行结果看图,图上可以看出ip的访问情况,7929和136770是这两个ip在access.log中出现的次数
2、blockip.sh脚本代码
下面贴一下blockip.sh脚本代码,其中blockip.sh涉及到的blockip.conf、tempip、blocktemp需要自己创建空文件,并放入你的nginx目录下,我的nginx目录是/usr/local/nginx/conf
blockip.conf需要在nginx.conf中引用。编辑nginx.conf,将“include blockip.conf”写入到nginx.conf的server配置中
nginx.conf的配置和操作请查询相关资料,网上资料很多,这里就简单介绍下。
------------------------------------脚本源代码start-----------------------------
#!/bin/bash
max=15000 #ip访问超过15000次封禁(这个字数可以自己定)
confdir=/usr/local/nginx/conf/blockip.conf #存放封锁ip的文件
logdir=/usr/local/nginx/logs/access.log #nginx日志文件
tempip=/usr/local/nginx/conf/tempip #存放nginx日志中访问超1万5的ip的临时文件,有重复值
blocktemp=/usr/local/nginx/conf/blocktemp #备份blockip.conf的临时文件
echo "---开始清空blocktemp和tempip文件---"
>$blocktemp
>$tempip
echo "---开始备份blockip.conf并读取nginx日志ip文件---"
cat $confdir >>$blocktemp #开始备份
cat $logdir | awk '{print }' |sort |uniq -c|sort -n |while read line #读取nginx日志文件的ip信息
do #循环开始
a=(`echo $line`)
if [ $a -ge $max ] #if判断 a大于max时执行echo
then
echo "deny ${a[1]};">>$tempip #将nginx日志文件的ip写入到temp中
fi
done #循环结束
cat $blocktemp >>$tempip #将blocktemp内容读入到tempip
>$confdir #清空封锁ip的文件
cat $tempip | sort|uniq>>$confdir #过滤重复ip,取独立ip放入blockip.conf
echo "---符合封禁的ip存入封禁文件 ---"
echo "---开始判断重启nginx---"
notice=0 #通知nginx重启0通知, 1不通知
reload=0 #是否重启nginx0不重启,1重启
while read conflog #开始判断有新的超过次数的ip,是否通知nginx重启
do
echo '---读取最新ip:conflog='${conflog}
while read line #读取blocktempip,和tempip比对,有新ip则通知重启
do
echo '---已封禁ip:line='${line}
if [ "$conflog" = "$line" ] #判断ip相等
then
notice=1
echo '---ip已存在notice='${notice}'----'
else
v=0 #随便写了一行,防止无内容报错
echo '---ip不相同---'
fi
done < ${blocktemp}
if [ "$notice" -eq 0 ] #notice=0通知nginx重启,否则notice置为0继续循环
then
reload=1
echo '---通知nginx重启notice='{$notice}'---'
else
notice=0
echo '---不通知nginx重启---'
fi
done <${tempip} #循环结束
if [ "$reload" -eq 1 ] #reload=1重启nginx
then
echo '---正在重启nginx,reload='${reload}'---'
/usr/local/nginx/sbin/nginx -s reload
echo '---nginx重启完毕---'
else
v=0 #随便写了一行,防止无内容报错
echo '---不重启reload='${reload}'---'
fi #脚本结束
------------------------------脚本源代码end----------------------------------------
脚本中echo 是打印信息到控制台,可以使用“#”将其注释,例如#echo ---
上面的方面是永久封禁ip,需要定时解封ip,懂Xsell脚本代码的自行修改,像我一样的新手小白,解封ip参考文章最上面的那个链接。解封ip的思路就是将blockip.conf中的ip删除或注释并重启nginx。
3、crontab 定时器设置,定时启动脚本
crontab -l 查看定时器
crontab -l
*/30 * * * * /usr/local/nginx/conf/blockip.sh # 每半小时定时启动,判断nginx访问次数超过7500的ip,封禁ip
编辑定时器
crontab -e
......
自行编辑
可根据自身需求设置定时启动时间
4、注意事项和脚本执行时出现的问题
blockip.sh代码粘贴到本地后,保存为blockip.sh文件,并放入nginx目录/usr/local/nginx/conf/
chmod +x blockip.sh 赋予文件root权限
./blockip.sh 手动执行脚本文件
如果执行报错
syntax error: unexpected end of file
这是因为在window环境下编写的或生成的文件,传到linux服务器上,doc下的文本内容格式和linux下的格式有所不同,比如dos文件传输到unix系统时,会在每行的结尾多一个^M结束符。或者是因为doc下的换行符和liunx的换行符不一样
参考解决方式:
其他解决方式:自己在liunx上用vi命令手打,但是需要注意脚本代码的使用规范,例如下面的编辑脚本时会出现的问题
类似下面这样的,一般是代码有问题。
syntax error near unexpected token `then'
代码要规范,例如 if [ $a = $b ] [ ] 括号前后应都有空格等
变量赋值,例如notice=0 等号两边不可以留空格等
参考:
网上关于脚本命令的资料很多,这里就简单解释下。
blockip.sh 脚本代码,亲测可用。不能跑起来的看下我上面说的几个注意事项。源代码下载放在文章最后,有需要的自己下载
最后说下,该脚本代码参考文章最上面的文章链接,我做了下修改,修改后不用频繁启动nginx,有新的访问次数超过规定值的ip才会重启nginx,旧的已经被存入blockip.conf的ip不会重新启动nginx
附图blockip.conf、tempip、blocktemp的内容示例。
7、 blockip.sh文件网盘下载
链接:https://pan.baidu.com/s/1EmDdBZOh1eUctPxoJQHa3A
提取码:8sef
8、追加一下刚刚浏览觉得不错的,其他博客的nginx自动封锁爬虫 方法
9、20200415追加,nginx封禁ip后,爬虫再访问为返回403错误,会记录到access.log日志中,每天的nginx日志文件过大,修改nginx.conf配置文件,使得403错误不被记录。(使用该方法可直接屏蔽爬虫,不用封ip,但是前提要确定是爬虫,并知道爬虫通过什么方式来爬的,我这里的爬虫是通过python爬的)
https://www.linuxidc.com/Linux/2014-07/104686.htm 可参考
我参考的这个
实际做法: 将红框代码放入到server location 下。
爬虫为python请求,使用user-agent 过滤,返回错误码505 不会被记录到access.log(原理我还不清楚),不过查了下nginx 505错误。
HTTP 505错误是HTTP状态码的一种,表示"HTTP版本不受支持",当服务器不支持请求中所使用的HTTP协议版本时就回返回此错误,最为常见的是 HTTP/1.1。