本文主要介绍如何使用 fail2ban 来削弱针对ssh的猜密码攻击。Ubuntu上自带的 fail2ban 默认规则有些小问题,看似不能直接生效。本文对系统自带 fail2ban 规则做了些修改,实际在Ubuntu Linux 14上测试可用。
清明假期的时候闲的没事将主机从AWS迁移出来了,blog平台也换成了WordPress。新的主机在所在的网段被无聊的人扫来扫去(有种回到校园网的感觉),而且有不少尝试对ssh的攻击,本着“不折腾不会死”的做死精神,在新的主机上启用了fail2ban。
新的主机跑的是Ubuntu Linux的,使用系统默认配置的fail2ban之后发现其实是不生效的。上网搜了一下发现不少人在抱怨fail2ban不能用。这周末自己闲在家里稍微研究了一下,原来是Ubuntu默认安装的fail2ban规则和系统auth.log产生的log不能匹配造成的。
简单记录一下让Ubuntu Linux上的fail2ban来阻挡ssh猜用户名/密码的攻击方法:
- 保证机器的时间正确(时区也看看),安装fail2ban(参考这里)。
- 启用ssh证书认证(对,这个和fail2ban没任何关系,但总比用密码认证安全些),具体参考这里: How To Set Up SSH Keys
- 看一下/var/log/auth.log中的sshd的报错,我这里放几个我遇到的比较典型的(student是随便一个用户名,10.1.1.1是任意的一个ip,example.com是任意的域名):
- Invalid user student from 10.1.1.1
- Received disconnect from 10.1.1.1: 11: Bye Bye [preauth]
- Address 10.1.1.1 maps to example.com, but this does not map back to the address – POSSIBLE BREAK-IN ATTEMPT!
- reverse mapping checking getaddrinfo for example.com [10.1.1.1] failed – POSSIBLE BREAK-IN ATTEMPT!
- copy /etc/fail2ban/filter.d/ssh.conf /etc/fail2ban/filter.d/bad-ssh.conf
- vi (或者你任何喜欢的文本编辑器,别和我争论这点,我是习惯用vi了)bad-ssh.conf,修改成以下内容:
[INCLUDES] before = common.conf [Definition] _daemon = sshd failregex = Received disconnect from : .*: Bye Bye \[preauth\] Address maps to .* POSSIBLE BREAK-IN ATTEMPT!$ Invalid user .* from $ Did not receive identification string from reverse mapping checking getaddrinfo for .* \[\] failed - POSSIBLE BREAK-IN ATTEMPT!$ ignoreregex =
- 修改/etc/fail2ban/jail.local,增加下面一段内容
[bad-ssh] enabled = true port = ssh filter = bad-ssh logpath = /var/log/auth.log action = iptables[name=sshd, port=ssh, protocol=tcp] maxretry = 2 bantime = 36000
- [optional] 修改 /etc/fail2ban/action.d/iptables-blocktype.conf,我是认为直接drop就好了,对这种无聊的攻击没义务发icmp port unreachable回去
# Option: blocktype # Note: This is what the action does with rules. This can be any jump target # as per the iptables man page (section 8). Common values are DROP # REJECT, REJECT --reject-with icmp-port-unreachable # Values: STRING #blocktype = REJECT --reject-with icmp-port-unreachable blocktype = DROP
- 执行service fail2ban restart,注意观察/var/log/fail2ban.log和auth.log,再有攻击发生会能看到类似下面的日志:
2014-04-19 17:47:29,215 fail2ban.actions: WARNING [bad-ssh] Ban 10.1.1.1
如果想要测试自己写的正则表达式是否正确,可以使用fail2ban自带的”fail2ban-regex”来测试,从auth.log中找出自己想匹配的一条日志,然后执行一下这个命令来试试看自己写的表达式是否会匹配即可。例如下面的例子:
root@hostname:~# fail2ban-regex 'Apr 19 18:55:07 hostname sshd[9146]: Received disconnect from 10.1.1.1: 11: Bye Bye [preauth]' 'Received disconnect from ' Running tests ============= Use failregex line : Received disconnect from Use single line : Apr 19 18:55:07 hostname sshd[9146]: Received dis... Results ======= Failregex: 1 total |- #) [# of hits] regular expression | 1) [1] Received disconnect from `- Ignoreregex: 0 total Date template hits: |- [# of hits] date format | [1] MONTH Day Hour:Minute:Second `- Lines: 1 lines, 0 ignored, 1 matched, 0 missed root@hostname:~#
需要注意,如果日志里面有中括号([])等特殊字符,记得要用正则表达式的转义字符”\”来匹配。要想匹配的更准确些,还可以考虑用上”$”(行尾)”^”行首等等……正则表达式怎么写就不多说了,网上的教程一大堆……
最后还是要多废话几句,fail2ban不能完全阻止所有的针对ssh的攻击,只能靠暂时封禁来削弱这种攻击的强度。定期看系统日志,发现潜在异常并且根据日志来进行相应的调整是系统管理员必须要做的事情。