fail2ban入侵防护

最近分析了系统访问日志,发现了很多4xx的请求,居然有人在探测:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
404 /login
404 /owa/auth/x.js
404 /ecp/Current/exporttool/microsoft.exchange.ediscovery.exporttool.application
404 /owa/auth/logon.aspx
404 /.env
404 ///remote/fgt_lang?lang=/../../../..//////////dev/
404 /.env
404 /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
404 /plugins/elfinder/php/connector.php
404 /remote/fgt_lang?lang=/../../../..//////////dev/cmdb/sslvpn_websession
404 /owa/auth.owa
404 /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
404 /wp-login.php
404 /functionRouter
404 /login
404 /jenkins/login
404 /remote/login
404 /owa/auth.owa
404 /wp-content/uploads.php
404 /.env HTTP/1.1
400 /.env HTTP/1.1
404 /owa/auth/x.js
404 /owa/auth/logon.aspx
404 /sdk HTTP/1.1
404 /evox/about
404 /system_api.php

唉!看见了总不能不管吧!于是我想到了fail2ban!

fail2ban简介

fail2ban是一款Python语言编写的,基于日志的防暴力破解的工具,其核心思路就是基于日志记录,结合预判的行为,将可疑的IP加入防火墙的黑名单,以此来达到保护服务器的目的。

假设,某日志中经常出现某某IP尝试登录数据库时,报密码错误,我们是不是就可以判定此IP存在暴力破解数据库密码的可能呢?是不是可以将此IP自动加入黑名单,防止其继续实施暴力破解呢?

假设,我们的网站经常有某IP尝试访问一个不存在的后台管理员登录地址时,我们是不是可以将此IP加入黑名单呢?

。。。

是的,fail2ban可以自动帮我完成上面的操作:将可疑的IP自动关入监狱。

这里要注意的是:fail2ban是一款防暴力破解工具,仅仅是防,并不能杜绝!

安装fail2ban

在Ubuntu系统中,我们可以使用如下命令来安装fail2ban

1
apt install fail2ban

fail2ban默认会安装在/etc/fail2ban目录下。

启动fail2ban
我们可以将fail2ban加入开机启动:

1
systemctl enable fail2ban.service

也可以使用start来启动:

1
systemctl start fail2ban.service

查看fail2ban的运行状态如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
root@iZwz92w1juq9pn9br6ydb6Z:/var/log# systemctl status fail2ban.service
● fail2ban.service - Fail2Ban Service
Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2021-05-05 08:57:12 CST; 13h ago
Docs: man:fail2ban(1)
Process: 4285 ExecStop=/usr/bin/fail2ban-client stop (code=exited, status=0/SUCCESS)
Process: 4386 ExecStart=/usr/bin/fail2ban-client -x start (code=exited, status=0/SUCCESS)
Main PID: 4392 (fail2ban-server)
Tasks: 7
Memory: 10.4M
CPU: 23.184s
CGroup: /system.slice/fail2ban.service
└─4392 /usr/bin/python3 /usr/bin/fail2ban-server -s /var/run/fail2ban/fail2ban.sock -p /var/run/fail2ban/fail2ban.pid -x -b

如果看到了running状态,则证明此时的fail2ban已经启动成了,下面我们就可以自定义我们的防护规则了。

自定义防护规则

新增并配置jail(监狱)文件

fail2ban默认的配置文件是/etc/fail2ban/jail.conf ,但是以后如果更新,此文件会被覆盖,所以我们可以新增一个本地配置文件:

1
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

自定义异常行为规则

假设我们发现nginx日志中有IP访问不存在的登录地址,我们希望自动把这个IP写入黑名单拒绝访问,该如何实现呢?

假如我们的nginx日志格式是这样的:

1
2
166.249.79.184 200 GET /xxx/xx/ HTTP/1.1 3245 [05/May/2021:07:00:58 +0800]  Mozilla/5.0 (compatible; Googlebot/2.1;
ml) - - [::1]:4000 200 - 0.005

说明:这里的nginx日志是做了格式化的,主要是将IP和http状态码调整到了前面,具体格式如下:

1
log_format  main  '$remote_addr $status $request $body_bytes_sent [$time_local]  $http_user_agent $http_referer  $http_x_forwarded_for $upstream_addr $upstream_status $upstream_cache_status $upstream_response_time';

此时,我们可以在/etc/fail2ban/filter.d 下新增一个规则:
为了简单,我们可以复制一个模板:

1
cp nginx-http-auth.conf nginx-my-auth.conf

然后编辑其内容:

1
2
3
4
5
[Definition]

failregex = ^<HOST> 4\d{2} (GET|POST|HEAD) \/.*(admin|login).*

ignoreregex =

重点就是正则表达式中的内容,如果返回4xx,并且请求链接中包含admin|login等内容时,就将IP关入监狱。

此时规则我们已经建立好了,如何让规则生效呢?
编辑之前复制的jail.local 文件,在最后加入如下内容:

1
2
3
4
5
6
7
[nginx-my-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/my_access.log
maxretry = 1
bantime = 604800
findtime = 5

参数说明:

  • logpath: 需要fail2ban监控的日志文件地址。可以有多个文件,换行即可。

  • maxretry: 最大尝试次数

  • bantime:IP禁用时间,默认是秒,还可以带上m或h等单位。

  • findtime: 查找时间,默认单位是秒。
    这个配置的意思是:5秒之内,如果存在1次某IP命中了我们定的规则,将该IP禁用604800秒。

  • 使配置生效
    我们可以查看目前已经生效的配置:

    1
    2
    3
    4
    root@iZwz92w1juq9pn9br6ydb6Z:/etc/fail2ban# fail2ban-client status
    Status
    |- Number of jail: 1
    `- Jail list: sshd

目前显示,生效的配置只有sshd的,并没有我们新增的内容,使用reload命令可以使fail2ban重新加载配置:

1
fail2ban-client reload

此时再使用fail2ban-client status 命令,就可以看到我们自定义的规则生效了。

1
2
3
4
root@iZwz92w1juq9pn9br6ydb6Z:/etc/fail2ban# fail2ban-client status
Status
|- Number of jail: 2
`- Jail list: nginx-my-auth, sshd
  • 验证规则是否真的有用
    我们可以在浏览器中访问https://xxx.xx.com/admin
    然后在后台输入
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    root@iZwz92w1juq9pn9br6ydb6Z:/etc/fail2ban# fail2ban-client status nginx-my-auth
    Status for the jail: nginx-my-auth
    |- Filter
    | |- Currently failed: 1
    | |- Total failed: 1
    | `- File list: /var/log/nginx/my_access.log
    `- Actions
    |- Currently banned: 1
    |- Total banned: 1
    `- Banned IP list: 192.168.1.110

此时如果能够在Banned IP list 中看到自己的IP,说明规则已经验证通过,fail2ban已经正常工作了。

常用命令

如果误封了IP,我们可以主动解封:

1
fail2ban-client set nginx-my-auth unbanip IP

当然,也可以使用banip命令主动封一个IP。

查看具体规则的拦截情况

1
fail2ban-client status nginx-my-auth

启动/重启/关闭 fail2ban

1
systemctl start/restart/stop fail2ban.service

使用指定规则验证指定日志

1
fail2ban-regex /var/log/nginx/my_access.log  /etc/fail2ban/filter.d/nginx-my-auth.conf

查看fail2ban日志

1
more /var/log/fail2ban.log

这里有被ban的IP的记录。