
核心要点(TL;DR)
- 密钥登录是根治手段,Fail2ban是止血手段,DenyHosts适合老旧系统兜底。
- 先关密码登录再谈封禁,否则封禁只是降低噪音而非消除风险。
- Fail2ban默认sshd规则即可拦截绝大多数爆破,重点在确认日志路径与后端。
- 改端口只能减少扫描噪音,不能替代密钥认证与封禁策略。
为什么你的 22 端口天天被爆破
公网服务器只要开放 SSH 22 端口,几小时内就会收到成百上千次登录尝试。多数来自僵尸网络的无差别扫描,密码字典轮番轰炸,日志被刷满、CPU 被 PAM 认证拖慢,真正需要排查故障时反而找不到有用记录。本文面向要动手的运维和站长,给出从判断规模到落地封禁、再到密钥登录收口的完整步骤,重点讲清 DenyHosts、Fail2ban 与密钥登录三者的取舍,而不是堆砌工具。
先判断:爆破规模与来源
动手前先量化,避免盲目上工具。查看失败登录来源排名:
sudo grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20
sudo journalctl -u ssh --since "24 hours ago" | grep -c "Failed password"若单日失败次数过万、来源 IP 分散,说明是无差别扫描,封禁阈值可放宽;若集中在少数 IP 且用户名是 root、admin,属于定向尝试,应优先收紧认证方式。同时确认 sshd 是否已禁用 root 直接登录、是否开启密码认证:
sudo sshd -T | grep -Ei 'permitrootlogin|passwordauthentication|port'三种方案的能力对比
| 方案 | 作用 | 优点 | 局限 |
|---|---|---|---|
| DenyHosts | 解析 auth.log 写入 hosts.deny | 轻量、依赖少 | 仅 SSH、维护停滞、与 Fail2ban 冲突 |
| Fail2ban | 日志匹配后动态封禁 | 多服务支持、规则可调、自动解封 | 需正确配置日志路径与防火墙后端 |
| 密钥登录 | 取消密码认证 | 从根源消除爆破面 | 需先验证密钥可用,否则可能锁死 |
结论很明确:密钥登录是根治,Fail2ban 是止血,DenyHosts 只适合老旧系统兜底。三者不是并列选择,而是分层组合。
第一步:用 Fail2ban 止血
Debian/Ubuntu 安装并启用 sshd 规则:
sudo apt install fail2ban -y
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local在 jail.local 中确认或追加:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
findtime = 10m
bantime = 1h
ignoreip = 127.0.0.1/8 你的办公出口IPCentOS/RHEL 系把 logpath 换成 /var/log/secure,并确认后端为 firewalld 或 iptables。启动并验证:
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
sudo iptables -L -n | grep -i f2bstatus 输出中应看到当前封禁 IP 列表,iptables 中应出现 f2b 链。若列表为空但日志持续报错,多半是 logpath 写错或后端未生效,先解决这个再谈调参。
第二步:密钥登录收口
本地生成密钥并上传:
ssh-keygen -t ed25519 -C "ops@example"
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server新开一个会话验证免密登录成功,再编辑 /etc/ssh/sshd_config:
PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin prohibit-password
执行 sudo sshd -t 检查语法,通过后 sudo systemctl reload sshd。务必保留当前已登录会话不退出,用新会话复测;确认无误后再关闭旧会话。若担心误操作,可临时保留一个应急账号密码登录,验证完成后再关闭。
第三步:验证与回滚清单
- 确认 fail2ban 服务开机自启,status 中封禁数持续增长。
- 用
sshd -T确认 passwordauthentication 为 no。 - 检查 /etc/hosts.deny 是否残留 DenyHosts 规则,避免与 Fail2ban 重复封禁。
- 把办公出口 IP 加入 ignoreip,防止自锁。
- 记录回滚路径:云控制台 VNC 或救援模式可改回 sshd_config 并重启服务。
若使用云主机安全组或主机防火墙,可在防护建议处配合 AegisX 的登录防护与异常 IP 拦截能力,把封禁动作前移到边界,减少主机侧日志压力。
行动建议
今天就做三件事:先跑一遍失败登录统计确认规模,再装 Fail2ban 并核对 status 输出,最后配置密钥登录并关闭密码认证。改端口、换 DenyHosts 都不是优先项,先把认证入口收紧,爆破日志自然会降下来。改动前保留一个可用会话,是所有操作的前提。
常见问题(FAQ)
Fail2ban和DenyHosts到底该选哪个?
优先选Fail2ban。它基于日志正则匹配,支持sshd、Nginx等多服务,社区活跃、规则可定制;DenyHosts只针对SSH且维护停滞,仅适合无法安装Fail2ban的老旧系统兜底。两者不要同时启用,避免写同一份hosts.deny造成冲突。
只改SSH端口不改密钥登录,安全吗?
不够。改端口只能躲开无差别扫描,针对性的爆破仍可发现新端口。正确顺序是先配置密钥登录并验证可用,再关闭PasswordAuthentication,最后才考虑改端口减少日志噪音。三者叠加才是完整方案。
启用密钥登录后还能保留密码登录做备用吗?
不建议长期保留。可临时设置PasswordAuthentication yes过渡,确认所有运维终端密钥可用后立即改为no。若担心锁死,先保留一个已登录会话不退出,改完配置用新会话验证再关闭旧会话。
Fail2ban封禁后为什么还能看到爆破日志?
封禁只针对已触发阈值的IP,新IP仍会尝试;另外需确认bantime与findtime设置是否过短、firewalld/iptables后端是否生效。用fail2ban-client status sshd查看当前封禁列表,用iptables -L -n检查规则链是否真正下发。
误封了自己的IP怎么快速解封?
用fail2ban-client set sshd unbanip 你的IP立即解封;若已无法登录,通过云控制台VNC或救援模式进入,执行相同命令,或直接清空对应封禁链。建议提前把办公出口IP加入ignoreip,避免重复误封。