概述
你有过这样的经历吗?打开 VPS 的安全日志,密密麻麻全是类似的记录:
Failed password for root from 185.220.101.x port 43210 ssh
Failed password for root from 45.143.205.x port 12345 ssh
你的服务器正在被成千上万的 bot 尝试暴力破解密码。手动一个个封 IP?不现实。
Fail2Ban 就是来解决这个问题的。它监控日志文件,发现恶意行为就自动调 firewall 封掉对方的 IP。配好之后,你完全不用管它,24 小时替你值班。
准备工作
- 一台运行 Linux 的 VPS(本文以 Ubuntu 22.04 / 24.04 为例,CentOS 7+ 也适用)
- root 或 sudo 权限
- 已配置好 SSH 远程登录(否则封禁后自己也连不上)
- 防火墙已启用(UFW 或 firewalld 均可)
安装与配置
第一步:安装 Fail2Ban
# Ubuntu / Debian
sudo apt update
sudo apt install fail2ban -y
# CentOS / RHEL
sudo yum install epel-release -y
sudo yum install fail2ban -y
第二步:创建本地配置文件
Fail2Ban 安装后会自带一个配置文件,但不建议直接修改它。正确做法是创建一个 jail.local 文件,它的优先级更高:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local
第三步:配置核心参数
找到 jail.local 中的 [DEFAULT] 部分,修改以下内容:
[DEFAULT]
# 封禁时间:3600 秒 = 1 小时,配 -1 表示永久封禁
bantime = 3600
# 重置时间:600 秒内如果没有新违规,计数归零
findtime = 600
# 触发封禁的失败次数
maxretry = 3
# 允许你自己(白名单 IP),防止把自己锁在外面
ignoreip = 127.0.0.1/8 ::1
注意: ignoreip 一定要加上你自己的 IP!建议用 curl ifconfig.me 查一下当前公网 IP,然后加到白名单里,用空格分隔多个 IP。
第四步:启用 SSH 防护
在 jail.local 末尾添加(或取消注释并修改):
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
backend = systemd
maxretry = 3
bantime = 7200
findtime = 600
如果你修改了 SSH 端口(比如改成了 2222),要把 port = ssh 改成 port = 2222。
第五步:配置邮件告警(可选)
想让 Fail2Ban 封了 IP 时给你发邮件通知?加一段配置:
[DEFAULT]
# 发件人
sender = your_email@example.com
# 收件人
destemail = your_email@example.com
# 发邮件的动作
mta = sendmail
# 告警模板
action = %(action_mwl)s
如果你用云服务器(阿里云、腾讯云等),更推荐用钉钉机器人或企业微信 webhook 代替邮件,消息到达率更高:
[mail-whois-lines]
action = %(action_)s
whois lines
[dingtalk]
action = %(action_)s
echo "Fail2Ban: $(whois %(ip)s | head -5)" | curl -s -X POST -H 'Content-Type: application/json' -d '{"msgtype":"text","text":{"content":"Fail2Ban: IP %(ip)s 被封禁,日志行数:%(failures)s"}}' YOUR_WEBHOOK_URL
第六步:启动并设置开机自启
# 启动 Fail2Ban
sudo systemctl start fail2ban
# 设置开机自启
sudo systemctl enable fail2ban
# 查看运行状态
sudo systemctl status fail2ban
验证安装是否成功
检查服务状态
sudo systemctl status fail2ban
看到绿色的 active (running) 就对了。
查看被保护的 jail
sudo fail2ban-client status
你会看到类似输出:
Status
|- Number of jail: 1
`- Jail list: sshd
查看 SSH jail 的详细状态
sudo fail2ban-client status sshd
输出示例:
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 47
| - Journal matches: _SYSTEMD_UNIT=sshd.service
`- Actions
|- Currently banned: 2
|- Total banned: 5
- Banned IP list: 45.143.205.12 185.220.101.33
Currently banned 后面的 IP 就是当前被屏蔽的地址。
手动测试是否生效
打开第二个终端,故意输错 SSH 密码 3 次,然后在第一个终端执行:
sudo fail2ban-client status sshd
如果 Currently banned 增加了一个新 IP,说明配置完全生效了。
常见进阶玩法
封禁时间递增
不想每次只封 1 小时?可以用 bantime-increment 让封禁时间越来越长:
[DEFAULT]
bantime.increment = true
bantime.base = 300 # 第一次封 5 分钟
bantime.factor = 4 # 每次翻 4 倍
bantime.max = 86400 # 最长封 1 天
bantime.failcount = 5 # 5 次之后开始递增
这样,第一次违规封 5 分钟,第二次 20 分钟,第三次 80 分钟……直到封顶 1 天。
保护 Nginx / Apache
不仅保护 SSH,还可以保护 Web 服务:
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 5
[nginx-botsearch]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 5
恢复被误封的 IP
有时候自己的 IP 会被误封,手动解封:
# 解封单个 IP
sudo fail2ban-client set sshd unbanip 45.143.205.12
# 解封所有 IP
sudo fail2ban-client set sshd unbanall
常见问题
Q:我改完配置后 SSH 连不上了?
A:检查 ignoreip 里有没有自己的 IP。如果已经连不上,去云服务商的网页控制台用 VNC 登录服务器,修改 jail.local 加回白名单 IP。
Q:封禁时间太长了怎么办?
A:按上面的命令解封即可。或者调低 jail.local 里 [DEFAULT] 的 bantime 值,然后 sudo systemctl restart fail2ban 重启生效。
Q:用 Cloudflare 的话 IP 不准怎么办?
A:Cloudflare 的 CDN 会隐藏真实 IP。你需要在 jail.local 里加一行:forwarded for = true,这样 Fail2Ban 会从 X-Forwarded-For 头里取真实 IP。
Q:Fail2Ban 吃多少资源? A:非常轻量。默认配置下内存占用约 10-30MB,CPU 基本可以忽略。
结语
装好 Fail2Ban 之后,你基本可以忘记 SSH 暴力破解这回事了。一个 apt install、一个 jail.local 配置搞定,几十行的东西就能替你挡住成千上万次的恶意登录。
现在就去服务器上跑一遍吧,打开日志看一眼——你会庆幸自己早点装上它。