任何挂公网的 SSH 端口每天会收到几千到几万次扫描尝试。
真正的防线是禁用密码登录 + 只用密钥,但 fail2ban 作为第二道防线
能进一步降低日志噪音、屏蔽明显的恶意 IP 段。
安装
sudo apt install -y fail2ban
sudo systemctl enable --now fail2ban
配置(重点:local 覆盖,不动 .conf)
永远不要直接改 /etc/fail2ban/jail.conf——升级会被覆盖。改 .local:
/etc/fail2ban/jail.local:
[DEFAULT]
# 屏蔽时长:从 10 分钟开始指数退避,最多 1 周
bantime = 10m
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 1w
# 检测窗口:10 分钟内
findtime = 10m
maxretry = 5
# 不要 ban 自己
ignoreip = 127.0.0.1/8 ::1 192.168.0.0/16 10.0.0.0/8
# 后端:systemd journal(无 /var/log/auth.log 时必选)
backend = systemd
# 用 nftables 而不是默认的 iptables
banaction = nftables-multiport
[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
maxretry = 3
bantime.increment = true 让累犯越关越久:第一次 10 分钟,第二次 20,
然后 40、80...... 最长 1 周。绝大多数扫描脚本几次就放弃换下一个 IP。
启用 + 校验
sudo systemctl restart fail2ban
sudo fail2ban-client status
# Number of jail: 1
# Jail list: sshd
sudo fail2ban-client status sshd
# Currently failed: ...
# Currently banned: ...
# Banned IP list: 1.2.3.4 5.6.7.8 ...
实时观察
sudo tail -f /var/log/fail2ban.log
# 或者 journal:
sudo journalctl -u fail2ban -f
手动操作 IP
# 立即解封
sudo fail2ban-client unban 1.2.3.4
# 永久 ban
sudo fail2ban-client set sshd banip 1.2.3.4
验证 nftables 规则
sudo nft list set inet f2b-table addr-set-sshd
# table inet f2b-table {
# set addr-set-sshd {
# elements = { 1.2.3.4, 5.6.7.8 }
# }
# }
配合其它服务
fail2ban 自带几十个 jail(nginx-botsearch、postfix、recidive 等)。
常见组合:
[nginx-botsearch]
enabled = true
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 3
findtime = 2m
[recidive]
# 反复在多个 jail 触发的 IP,全局长期 ban
enabled = true
bantime = 1w
findtime = 1d
maxretry = 5
recidive 是元 jail:观察 fail2ban 自己的日志,把"在多个 jail 都被 ban
过"的 IP 长期屏蔽,效果非常好。
踩过的坑
- 把自己 ban 了:从 Console / out-of-band 连进去,
fail2ban-client unban <你的IP>,
然后把 ignoreip 加上你常用的 IP 段。 backend = systemd必须在[DEFAULT]段,写错位置会被忽略,filter 看
不到任何日志,但状态看着一切正常 —— 一定要看failed数字是不是在增长。- IPv6 时代,单 IP ban 几乎没意义;建议改
banaction = nftables-multiport[blocktype=drop]
按整段 ASN ban,或者干脆把 SSH 端口改成非 22,噪音少 90%+。
登录后参与评论。