自己写的网站,不知道为啥总是有很多恶意访问的ip,根本不是正常的用户访问之前也有想过是否可能是运营商的代理服务器出口ip,但是看起来好像也不像,先不管,ban掉再说
那如何来ban呢,规则比较简单,就是超过一个阈值之后,就用下面的iptables命令
iptables -I INPUT -s <ip-to-ban> -j DROPservice iptables saveservice iptables restart
那如何统计nginx的访问ip呢,目前来说比较简单就是读取nginx的access.log文件,然后分析一下,如果一天超过阈值,我们就执行上面的命令,ban掉ip。有个问题是我们需要的是一直监视access.log 文件,而不是读一次,当然可以在每天快结束的时候事后来封住ip,但是这样不能给爬虫嚣张的气焰,所以我觉得立即封掉是比较OK的。
由于nginx的access.log每天都会做一次logrotate,它是怎么做的呢,nginx官网的推荐方式
mv access.log access.log.0kill -USR1 `cat master.nginx.pid`sleep 1gzip access.log.0 # do something with access.log.0
我的vps上面使用的是logrotated来处理的,可以在/etc/logrotate.d/nginx
/var/log/nginx/*.log { daily missingok rotate 52 compress delaycompress notifempty create 640 nginx adm sharedscripts postrotate [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid` endscript}
这里表示的create表示文件会重新创建。这里为了能够检测到文件变化了,就假设20秒没读到数据就算文件rotate掉了我们就重新打开新文件一次.
这里附上代码
#coding=utf-8import sysimport reimport osimport urllibimport urllib2import datetimeimport time, osimport loggingimport jsonimport selectlogging.basicConfig(level=logging.DEBUG, datefmt='%Y%m%d %H:%M:%S', format='[%(asctime)s] %(message)s')"""iptables -I INPUT -s <your_ip> -j DROPservice iptables saveservice iptables restart本脚本主要是用来把恶意访问nginx的ip ban掉的脚本"""def close_file(): if g_log_file: try: g_log_file.close() except: passg_log_file = Noneg_log_file_name=Nonedef get_file(f): """ 自动切换文件 """ global g_log_file if not g_log_file: logging.info("open new file:%s"%f) g_log_file=open(f,"r") st_size = os.stat(f)[6] g_log_file.seek(st_size) time.sleep(3) return g_log_fileMAX_IP=7000def get_date(): return time.strftime("%Y%m%d")def ban_one_ip(ip): os.system("iptables -I INPUT -s %s -j DROP ; service iptables save ; service iptables restart;"%ip)def find_ip_and_ban(): for ip in ip_map: if ip_map.get(ip)>MAX_IP: print "ban ip, count %s:%s"%(ip_map.get(ip),ip) ip_map[ip] = 0 ban_one_ip(ip)today = Noneip_map = {}def process_log(lines): global ip_map; global today; now = get_date() if now != today: today = now ip_map = {} for line in lines: ip = line.split(" ")[0] count = ip_map.get(ip,0) count += 1 ip_map[ip]=count; find_ip_and_ban()SECONDS=20COUNT=50def run_loop(fname): global g_log_file last_have_data_time=None while True: tmp = 0; lines =[] f = get_file(fname) last_have_data_time=time.time() while True: line = f.readline() if not line: if time.time()-last_have_data_time>SECONDS: logging.info("didn't have data for %s seconds"%SECONDS) g_log_file=None break; time.sleep(2) logging.info("no data and sleep 2 second") continue last_have_data_time=time.time() lines.append(line) tmp+=1 if tmp>=COUNT: break else: logging.info('read time out') g_log_file=None break process_log(lines) logging.info("process lines:%s"%len(lines))def main(): logging.info("args:%s"%repr(sys.argv)) if len(sys.argv)<2: print "%s file" % sys.argv[0] sys.exit(0) run_loop(sys.argv[1])if __name__ == "__main__": main()
原文地址:如何禁掉nginx恶意访问ip, 感谢原作者分享。 可偏偏。多么温柔,一出口便是相互指责和嘲讽。