Fail2ban 误封导致 SSH 连接被立即关闭

SSH 报 kex_exchange_identification: Connection closed by remote host 时,多为 fail2ban 封了客户端 IP;给出诊断、救急与放宽策略。

#type / debug #status / growing #tech / security #resource / oracle-cloud #resource / ssh #platform / server

[!warning] 先确认不是真被攻击 同样的「连接被立即关闭」也可能是 sshd 崩溃或防火墙 RST。先用 fail2ban-client status sshd 看到自己的 IP 在封禁列表里,才能确定是误封。

Fail2ban 误封导致 SSH 连接被立即关闭

现象

本地 ssh -vvv 显示 TCP 握手成功,但在协议 banner 交换前被断开:

debug1: Connection established.
debug1: Local version string SSH-2.0-OpenSSH_for_Windows_9.5
kex_exchange_identification: Connection closed by remote host
Connection closed by 129.225.x.x port 22

特征:端口能通(不是超时),但 SSH 协议层还没开始就被踢。密钥、密码都还没验证,所以不是认证问题。

快速判断

在能登录的通道(带外控制台、已建立的旧会话、Tailscale)里执行:

sudo fail2ban-client status sshd
sudo fail2ban-client get sshd banned

Currently banned 大于 0 且列表里有你的公网 IP(curl ifconfig.me 查),即为误封。

根因

fail2ban 默认策略约为 findtime=600(10 分钟)内 maxretry=5(5 次失败)即 bantime=3600(封 1 小时)。多个 ssh -N -L 隧道并发、频繁重连或脚本反复尝试,会在短时间内堆高失败计数,触发封禁。封禁有到期时间,到期后自动恢复——这正是「过一会儿又能连上」的原因。

救急

封禁默认不持久化,重启即清:

# 在带外通道执行
sudo systemctl restart fail2ban        # 清空内存封禁
# 或直接重启实例(OCI)
oci compute instance action --instance-id <OCID> --action SOFTRESET

也可只解封单个 IP:

sudo fail2ban-client set sshd unbanip <你的公网IP>

预防:放宽 + 白名单 + 累犯加重

# /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true
maxretry = 20
findtime = 300
bantime = 600

# /etc/fail2ban/jail.d/recidive.local
[recidive]
enabled = true
logpath = /var/log/fail2ban.log
bantime = 604800   # 7 天
findtime = 86400
maxretry = 5

白名单写在 [DEFAULT]ignoreip

[DEFAULT]
ignoreip = 127.0.x.x/8 ::1 <你的公网IP>/32

动态公网 IP 会变化,因此放宽全局策略比依赖白名单更稳;白名单只作为当前 IP 的额外保险。

陷阱:jail.d 优先级高于 jail.local

fail2ban 加载顺序为 jail.conf → jail.local → jail.d/*,后者覆盖前者。把配置写在 jail.local 里可能不生效,因为 jail.d/*.conf(含发行版自带的 defaults-debian.confsshd.local)会覆盖同名 section。改配置要改 jail.d/ 下的文件,改完 systemctl restart fail2ban 并用 fail2ban-client get sshd maxretry 复核。

回归验证

sudo fail2ban-client status sshd
sudo fail2ban-client get sshd ignoreip
sudo fail2ban-client get sshd maxretry

确认 ignoreip 含你的 IP、maxretry 为放宽后的值,再从本地新建 SSH 会话验证可连。

创建于 2026/7/21 更新于 2026/7/21