0x01 前言

最近遭受大量扫描与各种渗透攻击,因为我的服务器配置了modsecurity保护nginx,所以目前还没有造成影响。

虽然通过waf可以阻隔恶意访问,但这个并不是长久的解决办法。为此,我决定配置fail2ban拦截恶意IP,以提高安全性。

0x02 准备

fail2ban简单来说就是通过不断读取设定的日志文件,并通过正则校验每条日志是否符合规则。

一旦符合,则提取日志中的IP地址与时间戳,然后写入到fail2ban的数据库中。写库的同时进行计数,如果该IP在设定的时间间隔内被匹配的次数超过阈值,则调用iptables,将其的请求reject。

为此,再继续之前需要准备以下内容:

  1. iptables
  2. 日志路径
  3. 拦截内容

0x02.1

在绝大部分的云服务商中,因为没有安全组的概念,所以iptables都是启用的,这时候就可以跳过此项。

但在诸如腾讯云、阿里云或亚马逊云等大型云服务商中,可以通过安全组控制公网连入的IP与端口。这种情况下,iptables一般是禁用的,这时候就需要检查相关服务:

从上方可以看到服务处于停止inactive (dead)的状态,通过以下命令可以看到并没有规则处于启用状态:

这时候就需要要启用并删除2条默认的规则:

0x02.2 日志路径

fail2ban支持使用通配符匹配日志路径,如:

如果需要匹配上面的日志,则需要写成以下形式即可:

当然,也可以写完成的路径。

0x02.3 拦截内容

因为是针对HTTP服务,所以只需要匹配HTTP响应码即可。

正常情况下只会返回2种响应码:200与404;如果后端无响应的话,会返还50x;但被modsecurity拦截的请求会返回403,一些需要授权的页面则会返还400。

所以在我的环境里主要针对产生403与400这2种响应码的IP进行拦截。

0x03 安装配置

安装非常简单,建议使用epel的源进行安装:

安装完成后先不要启动,首先进入软件的目录:

0x03.1 jail

先复制一份jail文件:

默认的jail.conf不要修改,以备日后参考。

在fail2ban中,会先读取 .conf 后缀名的文件,然后读取 .local 后缀名的文件;而且后读取的配置可以覆盖先读取的配置。

然后在jail.local最后添加以下内容:

以上每行内容的大致意义如下:

  • [ngx-log]:定义jail名称
  • enabled:是否启用该jail,默认的所有规则都没有该项,需要手动添加
  • port:指定封禁的端口,默认为0:65535,也就是所有端口,但可以在jail中设定
  • filter:指定过滤器名称
  • logpath:日志路径
  • action:达到阈值后的动作
  • maxretry:阈值
  • findtime:时间间隔
  • bantime:封禁时长
  • ignoreip:忽略的IP

在这里有几点要注意的:

  • logpath与action可以有多行,如action中的设定:
    • 调用iptables-multiport封禁目标IP访问的多个端口
    • 调用sendmail发送告警邮件
  • findtime不是检查日志的时间间隔,日志的检查是实时的。因为fail2ban自带数据库,所以可以在设定的时间内统计匹配次数
  • ignoreip添加后端服务器的IP或CDN的IP

0x03.2 action

自带的action完全可以满足我们的需求,如果需要手动编写,也非常简单。我们来看看上面jail.local中[ngx-log]这个jail的action:

在action.d目录中我们可以找到相应的内容,把注释去掉之后的内容如下:

从上面的内容可以发现该action定义了5种不同的动作,其中actionstart与actionstop为自动调用时所用的,另外3种则可以通过fail2ban-client调用。

为了方便自动化调用,上面的各种action都包含用“<>”符号包裹的变量,调用的时候只需要指定即可。

0x03.3 filter

过滤器也是很重要的一部分,主要提供匹配服务,使用正则寻找IP。在jail中指定需要调用的过滤器文件名即可完成调用工作:

如上面的配置,调用了filter.d目录下ngx-40x.conf文件中的过滤器:

我需要匹配的日志如下:

题外话:我屏蔽了sogou等一系列的爬虫,因为这些爬虫不但没有给我带来流量,而且每次爬行都像CC攻击一样,都不知道他们是怎样开发的

定义过滤模块有两个需要注意的点:

  1. 无需匹配完整日志
  2. 日志中需要有标准的日期格式字段

其实fail2ban只关心1个要素:日志中的IP地址。

所以可以在生成日志的时候可以将正常与不正常的日志分开存储,然后匹配规则这样写:

但我的并不是这样,而是所有日志都在同一个文件中,所以需要写成这样:

“<>”符号为固定的变量名称,用于匹配IP地址,往后需要匹配HTTP响应码,这里匹配403与400两种情况,至此已经完成匹配工作,fail2ban并不关心后面的内容,所以可以忽略。

如果有多条正则,可以换行添加。

建立完过滤文件后可以使用以下命令检查匹配情况:

在Results中的Failregex字段显示出有多少条日志符合要求;在Date template hits字段中可以看到有多少条日志被默认的时间正则匹配上。

而Lines字段则显示出该日志文件的行数等情况。

fail2ban对日志中的时间格式有要求,如果匹配不上则无法计算findtime,在这里需要考虑时间格式不标准的情况。

因此,需要手动编写时间的匹配规则,如以下日志:

比较明显的时间格式如下:

那么时间的匹配规则应该是这样的:

不过在写入过滤器的时候需要多加一个“%”符号,用于转义:

运行fail2ban-regex检查结果:

从上面的结果可以看出,自定义的时间匹配规则已经生效。

0x04 运行

完成陪之后即可启动fail2ban:

通过fail2ban-client可以进行一些简单的操作,如:封禁IP、解封IP与检查状态等:

其他更多操作请参考使用手册。

0x05 结语

如果需要使用邮件告警,请修改jail.local文件中的destemail字段为你的电子邮箱地址,然后在jail的action中添加:

fail2ban是建立在日志基础上的封禁软件,只有在日志足够详细的情况下才能发挥应有的作用。

在过去一个月的使用后发现,fail2ban可以很好地提高安全防护水平。