跳到主要内容

使用fail2ban防范Linux服务器SSH暴力登录尝试攻击

· 阅读需 8 分钟

今天偶然看了下服务器上的日志,结果发现有人在暴力尝试SSH登录:

因为服务器是实验室内部使用,只有校园网才能连接,所以在服务器的安全上就没怎么在意。见此状况,立刻用iptables禁掉了一些IP,比如说禁掉148.235.57.190:

$ sudo iptables -I INPUT -s 148.235.57.190 -j DROP

-I表示插入规则,INPUT是规则链,-s指定来源IP,-j指定要跳转的目标,DROP表示丢弃数据包。

禁掉之后,过一会儿发现又来一些新的IP地址发起攻击了。考虑到对方可能有不少IP,我总不能像这样手动禁止IP吧。于是,就找到了fail2ban

fail2ban

fail2ban通过监测指定的日志,对日志使用正则表达式匹配,当在一段时间内匹配到指定数量时,就采取相应的动作,一般是配置防火墙、邮件通知等。这个就叫jail。

安装

安装fail2ban比较简单,直接安装即可。为了实现邮件通知功能,装个mailutils,这个自带邮件服务器postfix

$ sudo apt install fail2ban mailutils

配置

fail2ban的配置文件位于/etc/fail2banfail2ban.conf是对程序的一些设置,jail.conf是对规则的配置。不过,官方建议不要修改.conf文件,而是使用.local文件。也就是说,应该配置jail.local文件(没有的话新建一个),而不是去修改jail.conf文件。fail2ban会先读取.conf,再读取.local,因此.local可以覆写与.conf中重复的项,而.local中没有的项就可以使用.conf提供的配置。也可以在jail.d目录下进行配置。

以下是我的/etc/fail2ban/jail.local配置示例:

[DEFAULT]
# 允许本地环回和内网访问
ignoreip = 127.0.0.1/8 192.168.3.0/24
# 邮件告知谁
destemail = user1@localhost

[sshd]
enabled = true
# 在10小时内重试5次,就禁止30天
maxretry = 5
bantime = 2592000
findtime = 36000
# 禁止并发送邮件
action = %(action_mwl)s

ignoreip表示忽略哪些IP地址段,可以配置多个IP地址段,用空格隔开。192.168.3.0/24表示192.168.3.0~192.168.3.255这个IP地址段,/24是掩码的一种表示,意思是前24位是网段,也就是子网掩码为255.255.255.0。

destemail是发送邮件的收件人,多个收件人用,分隔。

maxretrybantimefindtime表示:在findtime秒内有maxretry次符合规则的日志产生就禁止来源bantime秒。不过,由于处理时延,实际开始处理时可能次数比maxretry多一点。(注意“bantime”别拼写错了)

至于action,默认的动作是iptables-multiport,也就是配置iptables

jail.conf里预设了一些其它动作,比如禁止并发送邮件等,可以像示例那样使用。也可以使用/etc/fail2ban/action.d中的动作,需要传入相应的参数,可以参考jail.conf里的示例。

filter.d目录是对日志的过滤规则,默认有很多实用的规则。如果要自定义过滤规则,要注意:

  1. 可以配置多条正则表达式,每行一条,每匹配一条都会使得计数器+1
  2. 对于日志行,会先自动匹配日期时间,剩下的部分才执行配置的正则表达式匹配,且不要求全部匹配。如果自动匹配日期时间失败,则整行的匹配会失败。并且,自动匹配日期时间的行为无法配置。

命令行

当修改配置文件后,需要重新加载配置文件使其生效:

$ sudo fail2ban-client reload

重新加载配置文件后,也会重新扫描日志文件,重新执行jail。

查看配置了哪些jail:

$ sudo fail2ban-client status
Status
|- Number of jail: 1
`- Jail list: sshd

查看jail的详细信息,只需加上jail名即可,例如查看sshd:

$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 2
|- Total banned: 2
`- Banned IP list: 186.201.214.162 46.101.103.207

为了检查过滤规则是否有效,可以使用fail2ban-regex

# 检查日志行与正则表达式的匹配情况
$ fail2ban-regex '18-07-2008 12:13:01 [1.2.3.4] authentication failed' '\[<HOST>\] authentication failed'
# 检查日志与过滤规则的匹配情况
$ fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
# 检查日志与正则表达式的匹配情况
$ fail2ban-regex /var/log/auth.log "Failed [-/\w]+ for .* from <HOST>"

Results中,Failregex: x total表示有x条日志行匹配(可见发出了很多次攻击),Date template hits表示自动匹配日期时间时命中了哪些格式。

注意事项

当我们更改了时区后,然后日志的时间并没有修改过来,导致两者的时间不一致,这样fail2ban的工作就失效了。 解决办法:重启日志服务,保证两者的时间一致:

$ sudo systemctl restart rsyslog

sshd更改端口号后使用fail2ban需要注意在填写配置的时候也需要更改端口号,否则起不到禁止作用。 如果使用jail.conf中预设的action,设置port即可,否则设置action,传入合适的port参数。

iptables

这里并不打算详细介绍iptables,毕竟本文的主角是fail2ban

启动fail2ban服务后,会自动在iptables里加入f2b-xxx链(xxx是jail名):

$ sudo iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
f2b-sshd tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 22
...
Chain f2b-sshd (1 references)
target prot opt source destination

如果fail2ban误杀了某个IP,可以手动将其移除。例如移除f2b-sshd链中的第1条规则(从1开始):

$ sudo iptables -D f2b-sshd 1

参考文献