脚本代码参考: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中出现的次数

nginx封禁ip 300秒 nginx 自动封ip_封ip

2、blockip.sh脚本代码

下面贴一下blockip.sh脚本代码,其中blockip.sh涉及到的blockip.conf、tempip、blocktemp需要自己创建空文件,并放入你的nginx目录下,我的nginx目录是/usr/local/nginx/conf 

nginx封禁ip 300秒 nginx 自动封ip_封ip_02

blockip.conf需要在nginx.conf中引用。编辑nginx.conf,将“include blockip.conf”写入到nginx.conf的server配置中

nginx.conf的配置和操作请查询相关资料,网上资料很多,这里就简单介绍下。

nginx封禁ip 300秒 nginx 自动封ip_nginx_03

------------------------------------脚本源代码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 $1}' |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  查看定时器

nginx封禁ip 300秒 nginx 自动封ip_liunx脚本_04

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的内容示例。

nginx封禁ip 300秒 nginx 自动封ip_nginx_05

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 下。

nginx封禁ip 300秒 nginx 自动封ip_nginx封禁ip 300秒_06

              

nginx封禁ip 300秒 nginx 自动封ip_nginx封禁ip 300秒_07

爬虫为python请求,使用user-agent 过滤,返回错误码505 不会被记录到access.log(原理我还不清楚),不过查了下nginx 505错误。

HTTP 505错误是HTTP状态码的一种,表示"HTTP版本不受支持",当服务器不支持请求中所使用的HTTP协议版本时就回返回此错误,最为常见的是 HTTP/1.1。