使用fail2ban来应对nginx服务器的穷举账号密码攻击

在检查nginx的log的时候,常常在/var/log/nginx/下看access.log发现很多类似针对wordpress的密码穷举攻击:

[30/Jan/2015:06:33:01 +0800] "POST /wp-login.php HTTP/1.1" 200 4166 "-" "Mozilla/5.0 (Windows NT 5.1; rv:29.0) Gecko/20100101 Firefox/29.0" "-"

如果我们设置了简单的密码,那么这的确是一个安全隐患,今天就来配置fail2ban来防止这种攻击。

系统仍然是centos6.6,已经安装好了EPEL源,首先:

yum install fail2ban

当然,首先好好读了一番fail2ban的官方文档,接下来我们就通过nginx的access.log里面的POST信息来ban攻击者的ip。
在/etc/fail2ban/下

cp jail.conf jail.local

然后在jail.local里面添加新的规则,当然可以直接在jail.conf中修改,而fail2ban会先读取jail.conf中的配置然后读取jail.local中的配置,如果有重复就以jail.local为准,这么做是因为直接在jail.conf中修改的话fail2ban也许会冲突。
我们在jail.local尾部添加:

[nginx-post-passwd-limit]
enabled=true
filter=nginx-post-passwd-limit
action=iptables[name=nppl, port=http, protocol=tcp]
logpath=/var/log/nginx/access.log
findtime=3600
bantime=7200
maxretry=10

上面的意思是filter去filter.d下面找nginx-post-passwd-limit.conf文件;action去action.d下面找iptables.conf文件,后面的name自己取,用在建立iptables的chain命名上,port和protocol都是直接传递给iptables的;logpath是指这段规则去解析nginx产生的log文件;然后后面是指如果在3600s内发生了filter指定的事件超过10次的话,那么就把这个ip给ban总共7200s的时间,时间到了解ban。

然后在/etc/fail2ban/filter.d下添加nginx-post-passwd-limit.conf的filter文件,里面定义这条规则:

[Definition]
failregex=<HOST>.*POST.*wp-login\.php.*

通配访问ip,这个正则就是匹配POST到/wp-login.php的log信息的。

最后因为这里是直接在iptables里ban的ip,所以为了保险在jail.local的[DEFAULT]字段里ignoreip加上自己的ip,否则连不上vps就完了

然后fail2ban自己的log默认在/var/log/messages里面,为了方便查找在fail2ban.conf里改成logtarget = /var/log/nginx/fail2ban.log。
fail2ban -d测试一下配置文件有没有ERROR,然后就打开/etc/init.d/fail2ban start,这样fail2ban就开始工作了。
为了测试我用另一台pc来POST了几次/wp-login.php,然后就被ban掉了,当然过了指定的时间就解ban了:
f2b
实验完后我把那台PC的ip也加到了jail.local的ignoreip后面,然后试着POST了几次/wp-login.php,发现没有被ban,说明一切正常。

fail2ban其实是通过调用iptables来ban的ip,而且看了一下fail2ban的daemon在start的时候jail里的不同的filter在iptables建立对应的chain,stop的时候会删掉这些chain,因此不必担心会污染原来配置好的iptables。
f2b2

现在终于把穷举密码攻击的问题解决了,那么顺便来玩玩防止被扫描吧。有时候会有人拿工具扫站点的目录,正常用户通过首页进入根本不会去访问不存在的资源,如果存在有ip大量访问不存在的资源,那么可以肯定有人在扫网站准备攻击了。此时nginx的log里面就会有大量的404出现,就算是搜索引擎周期性访问资源也不会产生这么多404,于是我在/etc/jail.local里新建一个规则:

[nginx-404-limit]
enabled=true
filter=nginx-404-limit
action=iptables[name=n4l, port=http, protocol=tcp]
logpath=/var/log/nginx/access.log
findtime=10
bantime=7200
maxretry=10

然后在/etc/fail2ban/filter.d下新建一个对应的nginx-404-limit.conf,里面匹配404的nginx的log,如下:

[Definition]
failregex=<HOST>.*\s404\s.*
ignoreregex=<HOST>.*robots.txt.*\s404\s.*
            <HOST>.*rss.xml.*\s404\s.*

下面的例外是为了防止搜索引擎来读这些文件被ban掉,这样基本就ok了,重新启动/etc/init.d/fail2ban restart,然后在/var/log/nginx/fail2ban.log下发现:
fail2ban.filter [6253]: ERROR Error in FilterPyinotify callback: _strptime_time
去查了一下发现是fail2ban的一个bug:https://github.com/fail2ban/fail2ban/pull/906
但是似乎不影响使用,就不管它了,现在我用另一台pc测试访问不存在的目录,返回404几次后就被ban了
然后换一个ip去访问/robots.txt以及rss.xml,虽然返回了404,但是不会被ban掉,这说明符合预期
这样防扫描功能完成了

最后需要说明的是,fail2ban启动后会对之前的access.log全部读一遍,在fail2ban启动之前的非法访问仍然会被ban掉。另外fail2ban默认只开启了ssh密码访问次数过多就ban ip的功能,不过我开启了密钥登录所以别人不管尝试多少次都没用,所以fail2ban的这个功能我用不到。

使用fail2ban来应对nginx服务器的穷举账号密码攻击》有1个想法

发表评论

电子邮件地址不会被公开。 必填项已用*标注