Linux【c语言】日志分析+mysql+iptables 动态将SSH攻击者(暴力破解)添加进防火墙黑名单

其实这本并不是我要做的事情,故事的开始要从某论坛的一位求助者说起。。。。。。。。

某天,某论坛来了一位求助者,求助的内容无外乎就是那么几种,服务器搭建啊,操作系统怎么装不上啊,c语言编译器啊,软件怎么装不上啊,作业不会做啊等等等等,今天的这位就是不会做老师布置的作业来着,作业的内容就是搭建一个VNC服务器,一般来说,这类求助会被忽略掉,原因吗也不外乎就那么几种,这种渣渣题太简单,不做;太高端,做不好;轻易就能搜索引擎到的东西,不做;作业党,不帮;伸手党,绝对不帮;考试党,笑看考试,调戏之,然后根据具体情况在考试结束后酌情给出答案或方案;而这位除了太高端和考试党外几乎全占。。。。。但与其它人不同的是这位求助者之所以成功了(有时候意外总是会有的)更多的方面是因为他还提供了一个帐号,甚至于密码也提供了出来,而最让人不能接受的是,他公开的帐号竟然是root!!!!!!!,很不凑巧,那天就被我碰到了,更不凑巧的是,那天我心情很不错(= =),本来因为过滤掉的东西由于心情好于是就点了进去,在看到帐户和密码的时候,好奇心强的我于是就这么踏入了这条不归路。。。。。。。。

登陆进入主机后(暂时就这么叫吧,也不知道具体该怎么叫好= =),发现密码完全正确,这也就意味着我算拥有了这台主机的所有权限(除了物理权限= =),看在这位同学这么诚实的态度,我破例一次,帮他完成了作业,作业完成之后就停不下来了,首先我要查下这台主机的地理位置在哪里,呐尼,XXX医学院。。。。。。。。,够坑爹,敢情医学院不学医专攻计算机了(额。。。),好吧,于是乎,或许乎,大概乎,我是理解这位同学了。。。。。,不过我既然来都来了就不能不做点什么,做点我喜欢做的东西,比如创建一个帐号,并且拥有绝对权限(阴笑中。。。),对于这位同学,坑爹坑老师坑学校,但是我是很喜欢的(继续阴笑。。。),于是乎请神容易送神难,我这样就算“常驻”这台主机了,起初也就是在这里装装软件,编译一下新版本的软件等等,因为作为一个忠实的deb系linux用户来说我还是第一次使用rpm系发行版(什么我没告诉你老师的这台主机是CentOS吗,你记错了吧),但没多久就感觉没趣了,因为每个发行版核心理念都差不多,于是乎又开始找些别的东西玩,为了能够长久占用本主机(虽然一时无趣了,但保不准以后就有需要)于是我向老师大人请求,像我这种热爱学习并乐于助人的好网友思想觉悟又这么高(额。。。),就不要注销我的帐号了。虽然我并不清楚这位老师有没有看到我的请求,但有一点可以肯定的是我的帐号至今没有被注销,暂时先认为老师接受了我的请求。故事似乎有点长,而且已与命题完全脱离了,难道是太兴奋了?好吧,回到正题,过了兴致的我开始有意无意地去注意日志了,这一注意就引来了新的故事。。。。。。。

什么还有故事,好了故事至此结束了,我在日志中发现对这台主机竟然有人在暴力破解root密码,开什么玩笑,要root,直接找那位同学不就好了,费得着这么暴力吗,做为正义的我,既然看到了就不能当作没看到,虽然这本与我并没有一毛线关系,但乐于助人的我决定帮帮忙,以表老师大人没有注销我的帐号之情(虽然可能没有。。。),故事至此结束。。。。。。。。。

日志的分析首先是从/var/log/secure发现有攻击者待续且频繁地猜测密码,平均两到三秒猜测一次,但如果从该日志文件中提取这些猜测密码失败的攻击者并使用防火墙屏蔽的话似乎是一个不错的选择,但是我又发现了另一个日志文件,没错那就是/var/log/btmp,该日志文件里面记录的内容为试图登陆本机但并没有成功登陆的记录,但该文件并不像secure一样是一个完全的“文本文件”(我的意思是里面的内容完全是可见的ASCII字符),不过这不需要担心,因为我们有该文件结构的接口,我们只需要通过该接口将登陆失败的记录提取出来,并且计算失败的次数和攻击的频率,以此就可以动态地将攻击者地址提取出来记入数据库同时使用iptables将该地址进行屏蔽。

使用到的函数
struct utmp *getutent(void);
读取数据,每调用一次便读一条记录,直到读取完所有记录(最后返回NULL)
结构体utmp为

我们之需要关心的几个参数为ut_line,ut_host,ut_tv,分别表示登陆的设备(?),登陆者的地址和登陆的时间,我们的程序检测的是通过ssh登陆的记录,ut_line在这里是ssh:notty(可能并不是每台机器都是如此,要根据情况而定),这样我们可以每过一段时间检查日志文件,将日志文件中所有ut_line为ssh:notty的失败登陆的地址进行标记,我们创建一个链表,如果读入到的地址是一个链表中没有的记录则添加,将第一次读取到的时间作为攻击开始时间,并使用一个标记说明该节点是否需要加入黑名单,初值设为不需要,如果读到一个已存在于表中的地址则更新该节点中的数据,比如将登陆的次数加一,将攻击的时间记录为最后一次攻击时间(动态更新),所有记录检测完毕后对该表进行扫描,通过开始攻击时间、最后攻击时间、攻击次数来决定是否需要将该节点标记为加入黑名单,最后再一次扫描该表,将所有标记为需要加入黑名单的地址加入数据库并使用防火墙屏蔽掉,然后删除该节点,程序的思路大抵就是如此。这里我们就需要一个标准,一个判断是否需要加入黑名单的标准,我在这里的设定是所有记录攻击次数达到50次及以上的则没有商量余地,直接加入黑名单,因为正常行为绝不可能会连续50次登陆错误,当然考虑到多天日志的不断累加,有可能正常的错误登陆会比较多,所以在读取日志之前我们会对链表进行一次扫描,将那些没有被标记为黑名单的节点通过最后一次攻击时间与当前时间进行对比,如果超过24小时则删除该节点,当然这也仅是对于并不频繁的攻击,如果攻击的太过频繁那么会直接被加入黑名单,我们以攻击的时长(最后一次攻击-开始攻击时间)与攻击的次数的比来作为审判标准,这样虽然并不能百分百做到准备,但也可以将攻击的程度限制到最低,同样的我们也需要该程序持续不断地在后台进行运行,并且能够定时或不定时地读取日志,这就需要根据前一次检测的结果来判断下一次检测的时间,如果前次检测攻击过于频繁且后续检测的时间间隔较短,如果攻击频率有所下降则检测频率也会下降,我这里设定最高检测时间间隔为2小时,由于并没有认真计划过,所以这里并没有设计一个有效且完整的算法,只是简单地做了些判断。

这里数据库使用mysql,防火墙使用iptables
下面是该程序的代码

为了能够开机就能运行,我们写一个启动脚本,由于我这里的主机使用的还是sysvinit所以就写sysvinit服务脚本了

将其放入到/etc/init.d目录中,并使用chkconfig -add添加服务(文件名为ipblocker)

当然我们也可以再做多点,比如我们给出一个网页地址,将所有被屏蔽的攻击者地址公布出来,我就做了这么一个网页(你以为我设计将攻击者存入数据库是做吗子用的= =)

故事的最后,这其实并不是我本应该做的,但天要下雨,我要写代码做练习,这是碰上了,我就是这么蛋痛。。。。。 本文来自枯龙吟的博客

–阅读次数(98)

发表评论

电子邮件地址不会被公开。

*