使用fail2ban防范Linux服务器SSH暴力登录尝试攻击
今天偶然看了下服务器上的日志,结果发现有人在暴力尝试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/fail2ban
,fail2ban.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
是发送邮件的收件人,多个收件人用,
分隔。
maxretry
、bantime
、findtime
表示:在findtime秒内有maxretry次符合规则的日志产生就禁止来源bantime秒。不过,由于处理时延,实际开始处理时可能次数比maxretry多一点。(注意“bantime”别拼写错了)
至于action
,默认的动作是iptables-multiport
,也就是配置iptables
。
jail.conf
里预设了一些其它动作,比如禁止并发送邮件等,可以像示例那样使用。也可以使用/etc/fail2ban/action.d
中的动作,需要传入相应的参数,可以参考jail.conf
里的示例。
filter.d
目录是对日志的过滤规则,默认有很多实用的规则。如果要自定义过滤规则,要注意:
- 可以配置多条正则表达式,每行一条,每匹配一条都会使得计数器+1
- 对于日志行,会先自动匹配日期时间,剩下的部分才执行配置的正则表达式匹配,且不要求全部匹配。如果自动匹配日期时间失败,则整行的匹配会失败。并且,自动匹配日期时间的行为无法配置。
命令行
当修改配置文件后,需要重新加载配置文件使其生效:
$ 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