- 论坛徽章:
- 0
|
本帖最后由 ljwsy 于 2014-04-15 17:28 编辑
我自己构思了一个“ssh扫描封堵的实现过程”,用的是py实现,经过近两年的运行,效果还不错。脚本是用crontab来运行的,控制粒度为分钟,太低了点,对付慢扫是足够的,而对付脑残不管别人感受的狂扫则有点吃力:开5线程一秒的扫描,一分钟就有300+个记录,等程序反应过来添加防火墙后,这个记录量上升已成事实。
为改变这种现状,打算改用守护进程的方式监控。想法是这样的:脚本进程实时监控auth.log,一旦有新的扫描行则入库;每5分钟从库中提取触犯规则的IP重新生成防火墙规则;在重新生成防火墙规则之间的时间段中,只要某IP产生的扫描记录数超过6条,就把这IP加入临时违规并生成防火墙规则。
为实现上面的想法,我把auth.log重定向为守护进程的stdin,但我用下面的代码“监控”stdin时却只取到进程启动时当前stdin存在的行,新行则取不到(注:因为是测试脚本,不直接用auth.log作为输入,而是改用每分钟都有新行生成的sshdipfw.log)。- #!/usr/local/bin/python
- # -*-coding:utf-8-*-
- import sys, os, time
- fname='/tmp/sshd_new.pid'
- def daemonize(stdin='/dev/null',stdout= '/dev/null', stderr= 'dev/null'):
- if os.path.isfile(fname) :
- if (time.time()-os.path.getatime(fname)<300) :
- exit()
- #Perform first fork.
- try:
- pid = os.fork()
- if pid > 0:
- sys.exit(0) #first parent out
- except OSError, e:
- sys.stderr.write("fork #1 failed: (%d) %s\n" %(e.errno, e.strerror))
- sys.exit(1)
- os.chdir("/")
- os.umask(0)
- os.setsid()
- #fork
- try:
- pid = os.fork()
- if pid > 0:
- sys.exit(0) #second parent out
- except OSError, e:
- sys.stderr.write("fork #2 failed: (%d) %s]n" %(e.errno,e.strerror))
- sys.exit(1)
- #
- for f in sys.stdout, sys.stderr: f.flush()
- si = file(stdin, 'r')
- so = file(stdout,'a+')
- se = file(stderr,'a+',0)
- os.dup2(si.fileno(), sys.stdin.fileno())
- os.dup2(so.fileno(), sys.stdout.fileno())
- os.dup2(se.fileno(), sys.stderr.fileno())
- pid=open(fname,'w')
- print >> pid,'Daemon started with pid %d\n' % os.getpid()
- pid.close()
- def _example_main():
- sys.stdout.write('Daemon started with pid %d\n' % os.getpid())
- sys.stdout.write('Daemon stdout output\n')
- sys.stderr.write('Daemon stderr output\n')
- c = 0
- while True:
- for line in sys.stdin:
- sys.stdout.write('%s: %s' %( time.ctime(),line))
- sys.stdout.flush()
- c = c+1
- #time.sleep(1)
- if __name__ == "__main__":
- daemonize('/var/log/sshdipfw.log','/var/log/sshdipfw_new.log','/var/log/sshdipfw_new.log')
- _example_main()
复制代码 这是sshdipfw_new.log输出(stdout):- ……
- Sun Apr 13 23:30:36 2014: update at 2014-04-13 23:29:00.
- Sun Apr 13 23:30:36 2014: Total rule(s) -> 86
- Sun Apr 13 23:30:36 2014: update at 2014-04-13 23:30:00.
- Sun Apr 13 23:30:36 2014: Total rule(s) -> 86
复制代码 而新的sshdipfw.log(stdin)多出的几行则不见出现在sshdipfw_new.log(stdout)中:- ……
- update at 2014-04-13 23:29:00.
- Total rule(s) -> 86
- update at 2014-04-13 23:30:00.
- Total rule(s) -> 86
- update at 2014-04-13 23:31:00.
- Total rule(s) -> 86
- update at 2014-04-13 23:32:00.
- Total rule(s) -> 86
- update at 2014-04-13 23:33:00.
- Total rule(s) -> 86
- update at 2014-04-13 23:34:00.
- Total rule(s) -> 86
复制代码 呵呵,由于本人拿着比码农的一半不到的工资,自然水平也不会高到哪里去,通常都是碰到什么问题才会想着去解决什么问题,所以水平提高得非常的慢。在此想请教达人:在_example_main()段我怎样监控,如果有新行则取到新的行(如原来的最后行时间为23:30:00以及它下面的一行,这个点以后的都视为新行),再进行处理(原来我是从从文件头读取再对比时间——这样做效率太低)。
要不坛友有什么更好的办法指点指点也行,反正是要实现这功能:实时监控某文件,有新行则处理。
在此先谢谢您的指导,也谢谢来围观或回帖的坛友。 |
|