我们一直致力于
提供最优质的高防服务

nginx防ddos

unnamed-file-79

自己写的网站,不知道为啥总是有很多恶意访问的ip,根本不是正常的用户访问之前也有想过

是否可能是运营商的代理服务器出口ip,但是看起来好像也不像,先不管,ban掉再说

那如何来ban呢,规则比较简单,就是超过一个阈值之后,就用下面的iptables命令

iptables-IINPUT-s-jDROPserviceiptablessaveserviceiptablesrestart

那如何统计nginx的访问ip呢,目前来说比较简单就是读取nginx的access.log文件,然后分析一下,如果一天超过阈值,我们就执行上面的命令,ban掉ip。

有个问题是我们需要的是一直监视access.log文件,而不是读一次,当然可以在每天快结束的时候事后来封住ip,但是这样不能给爬虫嚣张的气焰,所以

我觉得立即封掉是比较OK的。

之前写过一个类似tail读取一个文件的功能,就是打开的时候先定位到文件大小的位置,然后就开始循环读行来处理,这次的处理有点不一样,我是直接使用tail把那个文件的流定位到我的程序的sys.stdin,这样就简单的可以读到所有的流了

tail/var/log/nginx/access.log|python.py

但是nginx的access.log每天都会做一次logrotate,它是怎么做的呢,nginx官网的推荐方式

mvaccess.logaccess.log.0kill-USR1`catmaster.nginx.pid`sleep1gzipaccess.log.0#dosomethingwithaccess.log.0

我的vps上面使用的是logrotated来处理的,可以在/etc/logrotate.d/nginx

/var/log/nginx/*.log{dailymissingokrotate52compressdelaycompressnotifemptycreate640nginxadmsharedscriptspostrotate

[-f/var/run/nginx.pid]&&kill-USR1`cat/var/run/nginx.pid`

endscript}

这里表示的create表示文件会重新创建。其实这样老的文件就没有新数据了,但是因为使用的是tail,也没有eof,这样直接读的时候会发现file.readline()的函数会卡住,导致程序假死,这样程序就不能主动退出了,后面选择了用select来处理,加了一个10秒的超时,从目前的流量来看,基本上每秒都好多的请求,10秒都没有数据就是出问题了。

whilesys.stdininselect.select([sys.stdin],[],[],10)[0]:

然后如果没有select上的话,说明基本上是nginxlog文件rotate掉了,所以遇到这样的情况,我就直接跳出程序,然后把程序终结掉。终结掉怎么办呢,本来想在程序里面重新启动一下程序,但是感觉可能不妥,所以使用crontab来处理了,每隔2分钟检查一下,为了防止多次启动就用了flock来防止程序重新启动

*/2****

flock-xn/dev/shm/blocker.lock-c"sh/srv/www/beauty/daemon/nginx_ip_blocker.sh"

这里附上代码#coding=utf-8importsysimportreimportosimporturllibimporturllib2importdatetimeimporttime,osimportloggingimportjsonimportselect

logging.basicConfig(level=logging.DEBUG,datefmt='%Y%m%d%H:%M:%S',format='[%(asctime)s]%(message)s')

"""iptables-IINPUT-s-jDROPserviceiptablessaveserviceiptablesrestart

本脚本主要是用来把恶意访问nginx的ipban掉的脚本

"""MAX_IP=7000defget_date():returntime.strftime("%Y%m%d")defban_one_ip(ip):

os.system("iptables-IINPUT-s%s-jDROP;serviceiptablessave;serviceiptablesrestart"%ip)

deffind_ip_and_ban():foripinip_map:ifip_map.get(ip)>MAX_IP:

print"banip,count%s:%s"%(ip_map.get(ip),ip)

ip_map[ip]=0ban_one_ip(ip)today=Noneip_map={}defprocess_log(lines):globalip_map;globaltoday;now=get_date()ifnow!=today:today=nowip_map={}forlineinlines:ip=line.split("")[0]count=ip_map.get(ip,0)count+=1ip_map[ip]=count;find_ip_and_ban()COUNT=50defmain():brk=FalsewhileTrue:tmp=0;lines=[]brk=False

whilesys.stdininselect.select([sys.stdin],[],[],10)[0]:

line=sys.stdin.readline()ifnotline:brk=Trueprint'readtoeof'breaklines.append(line)tmp+=1iftmp>COUNT:breakelse:brk=Trueprint'readtimeout'breakprocess_log(lines)print"readlines:%s"%len(lines)ifbrk:breakifbrk:print"breakout"if__name__=="__main__":main()

未经允许不得转载:路过高防 » nginx防ddos

热门文章

  • 评论 抢沙发

    • QQ号
    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址