Fail2Ban 安装与配置:给 VPS 装一个自动封 IP 的保安

概述

你有过这样的经历吗?打开 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 配置搞定,几十行的东西就能替你挡住成千上万次的恶意登录。

现在就去服务器上跑一遍吧,打开日志看一眼——你会庆幸自己早点装上它。

这篇文章对你有帮助吗?