Ubuntu服务器如果直接暴露SSH端口到公网,几乎每天都会遭受大量暴力破解攻击,日志里密密麻麻全是"Failed password"的记录。fail2ban是一款轻量级但极其有效的入侵防御工具,它通过监控系统日志文件,自动识别重复失败的登录尝试,并动态更新防火墙规则将攻击IP封禁。安装配置fail2ban后,你的SSH端口基本不会再被爆破成功,同时万一误封了自己或同事,也能通过简单命令快速解禁。下面从安装、配置SSH防护、自定义规则、误封处理到长期运维,一步步讲清楚。

一、为什么Ubuntu必须部署fail2ban

Ubuntu默认开启SSH服务,端口22对全世界开放。如果你用的是云服务器,基本上上线几分钟就会收到第一波扫描。暴力破解的原理很简单:攻击者用字典不断尝试用户名和密码组合,直到猜对为止。fail2ban的核心机制是"次数触发封禁"——当某个IP在规定时间内失败次数超过阈值,就自动把这个IP加入iptables或nftables的黑名单,直接丢弃它的所有后续连接请求。这比单纯靠强密码安全得多,因为它从网络层面就把攻击者挡在了外面。

二、安装fail2ban及基础依赖

Ubuntu 20.04和22.04的软件源里都有fail2ban,直接用apt安装即可。安装前确保系统的防火墙工具已经就绪,fail2ban支持iptables、nftables和firewalld,Ubuntu默认用的是iptables配合ufw。

sudo apt update
sudo apt install fail2ban -y
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo systemctl status fail2ban

安装完成后fail2ban会自动运行,但默认配置对SSH的防护力度不够,需要手动调整。注意不要直接修改/etc/fail2ban/jail.conf这个文件,正确做法是创建/etc/fail2ban/jail.local来覆盖默认配置,这样升级软件时不会丢失你的自定义设置。

三、配置SSH防爆破的核心参数

创建jail.local文件,写入针对sshd的防护规则。以下是一套经过实战验证的推荐配置:

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
findtime = 600
bantime = 3600
action = ufw

逐个解释这些参数的含义。maxretry = 5表示5次失败登录就触发封禁;findtime = 600表示在600秒(10分钟)的时间窗口内累计5次失败才算;bantime = 3600表示封禁时长为3600秒(1小时)。这套参数的意思是:某个IP如果在10分钟内连续输错5次密码,就会被防火墙封禁1小时。对于正常用户来说几乎不可能触发,但对暴力破解脚本来说足够致命。

如果你的服务器安全要求更高,可以把bantime调到86400(24小时),maxretry降到3,findtime降到300。但要注意,参数太激进会增加误封风险,尤其是你自己用密码登录时如果手滑输错几次就会被锁在外面。

四、自定义filter规则应对复杂攻击

fail2ban自带的sshd filter已经能覆盖大多数情况,但有些攻击者会用不同的方式尝试登录,比如用密钥认证失败、用不存在的用户名尝试等。你可以查看默认filter文件了解它匹配的正则表达式:

sudo cat /etc/fail2ban/filter.d/sshd.conf

如果你发现某些攻击没有被识别,可以创建自定义filter。比如你想同时封禁那些尝试用root用户名爆破的IP,可以在/etc/fail2ban/filter.d/sshd.local中追加规则(注意文件名必须以.local结尾才会覆盖默认配置):

[Definition]
_groupsre = (?:error: PAM: )?authentication failure(?:; .*)? rhost=<HOST>(?:\s+port=\d+)?(?:\s+user=root)?
failregex = ^%(__prefix_line)s(?:error: PAM: )?authentication failure(?:; .*)? rhost=<HOST>(?:\s+port=\d+)?(?:\s+user=root)?
            ^%(__prefix_line)sFailed (?:password|publickey) for .* from <HOST> port \d+ ssh2

自定义filter写好后重启fail2ban使其生效:

sudo systemctl restart fail2ban

五、误封了怎么办?快速解禁的完整操作

这是实际运维中最常见的问题。你可能因为输错密码、换了新设备登录、或者同事用了不同的网络IP,结果自己被封了。解禁方法有三种,根据场景选择。

第一种:查看当前被封禁的IP列表。先确认哪个IP被封了,以及是哪个jail触发的:

sudo fail2ban-client status sshd

输出会显示当前被封禁的IP地址列表,类似这样:

Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed: 127
|  `- File list: /var/log/auth.log
`- Actions
   |- Currently banned: 2
   |  |- IP list: 203.0.113.45 198.51.100.22
   |  `- Banned time: 2024-01-15 14:30:00
   `- Total banned: 45

第二种:解禁指定IP。找到你要解禁的IP地址,执行:

sudo fail2ban-client set sshd unbanip 203.0.113.45

第三种:如果你不确定是哪个IP被封,或者想解禁所有IP(紧急情况下),可以:

sudo fail2ban-client set sshd unbanall

但unbanall会把所有被封的IP都放出去,包括真正的攻击者,所以不到万不得已不要用。更安全的做法是先查status确认,再逐个unbanip。

六、设置白名单避免误封自己和信任IP

与其每次被封了再解禁,不如提前把信任的IP加入白名单。fail2ban的ignoreip参数可以指定永远不封禁的IP或网段。在jail.local的[DEFAULT]段添加:

[DEFAULT]
ignoreip = 127.0.0.1/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 你的固定公网IP

把你自己常用的办公网络IP、公司出口IP都加进去。注意如果你是动态IP,每次换网络都要更新这个列表,否则就会被封。更好的方案是配合密钥认证登录SSH,这样根本不会触发密码失败计数,fail2ban对密钥认证失败的处理也需要单独配置。

七、配合SSH密钥认证从根源降低风险

fail2ban是被动防御,更主动的做法是禁用SSH密码登录,只允许密钥认证。这样暴力破解根本没有意义,因为没有密码可以试。修改/etc/ssh/sshd_config:

PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
UsePAM yes

修改后重启SSH服务:

sudo systemctl restart sshd

注意:在执行这步之前,一定要确认你已经把自己的公钥部署到了服务器的~/.ssh/authorized_keys里,否则你会把自己锁在外面。这是新手最容易犯的致命错误。

八、监控fail2ban运行状态和日志

fail2ban自身的日志在/var/log/fail2ban.log,可以实时查看它的运行情况:

sudo tail -f /var/log/fail2ban.log

你会看到类似这样的记录,显示哪个IP被封了、封禁了多久、触发了哪条规则。如果你想长期监控,可以配置fail2ban的邮件通知功能,在jail.local的action里加上发送邮件的动作:

action = %(action_mwl)s

这样每次有IP被封禁,fail2ban会给你发一封邮件,包含被封IP、触发时间、相关日志片段。这对于无人值守的服务器来说非常实用,能第一时间发现异常。

九、多jail联动防护其他服务

fail2ban不只能防SSH,还可以保护Nginx、Apache、Docker、MySQL等任何有日志的服务。比如你的Web服务器也经常被扫描,可以加一个nginx-http-auth的jail:

[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 6
findtime = 600
bantime = 7200

多个jail同时运行,fail2ban会监控所有指定的日志文件,任何服务遭到暴力破解都会被自动处理。但要注意,jail太多会增加系统资源消耗,对于低配服务器建议只开必要的几个。

十、长期运维建议和注意事项

第一,定期检查fail2ban的封禁列表,确认没有大量误封。如果某个IP段频繁被封又频繁解禁,可能是你的白名单没配好。第二,bantime不要设成永久(-1),因为攻击者的IP可能会被回收给正常用户,永久封禁会误伤无辜。第三,fail2ban的规则文件要定期更新,新版本可能会修复已知的正则匹配问题。第四,如果你用的是ufw防火墙,确保fail2ban的action配置和ufw兼容,否则封禁规则可能不会生效。

总结一下,fail2ban在Ubuntu上防SSH爆破是一套非常成熟的方案,核心就是"监控日志+动态封禁+白名单保护+误封解禁"这四步。装好配置好之后基本不用管,它会在后台默默帮你挡住绝大多数攻击。唯一需要你注意的就是别把自己封了,以及定期看看日志确认一切正常。