
核心要点(TL;DR)
- SSH被爆破的根治方案是关闭密码登录改用密钥,fail2ban只是补刀。
- 改sshd配置前先保留一个已登录会话,避免改错把自己锁在门外。
- fail2ban的banaction要与实际防火墙匹配,否则封禁不生效。
- 密钥登录需同时禁用root密码与空密码,并定期审计authorized_keys。
凌晨三点收到告警,登录服务器一看 /var/log/auth.log 里全是 Failed password for root,一分钟几百条——这是绝大多数运维和站长都遇到过的场景。SSH 暴露在公网,被暴力破解几乎是必然事件。本文不讲空泛理论,直接给出从确认现状、切换到密钥登录、到用 fail2ban 自动封禁的完整操作路径,照着执行即可把爆破噪音压下去,并显著降低被撞库成功的风险。
一、先确认:你的 SSH 到底被爆破到什么程度
动手前先取证,避免盲目改配置。核心是看认证日志里的失败与成功记录:
# Debian/Ubuntu
sudo grep "Failed password" /var/log/auth.log | wc -l
sudo grep "Accepted" /var/log/auth.log | tail -20
# CentOS/RHEL
sudo grep "Failed password" /var/log/secure | wc -l
sudo lastb | head -20 # 失败登录来源
sudo last | head -20 # 成功登录记录重点看两件事:失败来源 IP 是否高度集中、是否存在你不认识的 Accepted publickey/password 记录。同时确认当前认证方式:
sudo sshd -T | grep -Ei 'passwordauthentication|permitrootlogin|pubkeyauthentication|port'如果 passwordauthentication yes 且 permitrootlogin yes,那么爆破只是时间问题,必须进入下一步加固。
二、根治手段:切换到 SSH 密钥登录并关闭密码
暴力破解之所以有效,是因为密码可被猜测。关闭密码认证后,爆破日志会迅速归零。操作顺序很关键,务必先保留一个已登录的 SSH 会话不要断开,新开窗口验证成功后再退出旧会话。
1. 本地生成密钥并上传公钥
ssh-keygen -t ed25519 -a 100 -C "ops@example"
ssh-copy-id -i ~/.ssh/id_ed25519.pub ops@your_server_ip若服务器禁用密码无法用 ssh-copy-id,可手动追加:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo "ssh-ed25519 AAAA... ops@example" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys2. 修改 sshd 配置
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo vi /etc/ssh/sshd_config确认以下项(无则新增):
PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin prohibit-password
ChallengeResponseAuthentication no
UsePAM yes
MaxAuthTries 3
LoginGraceTime 20校验并重载,不要直接 restart,先测试语法:
sudo sshd -t
sudo systemctl reload sshd # 或 ssh新开终端用密钥登录验证成功后,再关闭旧会话。若登录失败,用旧会话回滚备份配置即可。
三、补刀手段:用 fail2ban 自动封禁爆破源
关闭密码登录后仍有扫描与密钥探测流量,fail2ban 能按日志自动封禁来源 IP。安装:
sudo apt install fail2ban # Debian/Ubuntu
sudo yum install epel-release && sudo yum install fail2ban不要改 jail.conf,新建 /etc/fail2ban/jail.local:
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 你的办公出口IP
[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
banaction = iptables-multiportbanaction 必须与系统防火墙匹配,否则规则写了也不生效:
| 系统防火墙 | 推荐 banaction |
|---|---|
| iptables | iptables-multiport |
| firewalld | firewallcmd-rich-rules |
| nftables | nftables-multiport |
启动并验证:
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 1.2.3.4 # 误封时解封看到 Currently banned 有数值、Banned IP list 持续增长,说明规则已生效。
四、加固检查清单与回滚要点
- 已保留可用 SSH 会话,改配置前备份
sshd_config。 sshd -t语法通过后再 reload。- 密钥登录验证成功,密码认证已关闭。
- root 仅允许密钥登录,普通运维账号使用 sudo。
- fail2ban 的 banaction 与实际防火墙一致,白名单含办公出口 IP。
- 定期审计
~/.ssh/authorized_keys,删除陌生公钥。
回滚口诀:旧会话不断、配置有备份、reload 不 restart、白名单先加人。
五、行动建议:把防护做成常态
完成上述步骤后,爆破日志会从每分钟数百条降到零星扫描。建议再做三件事:为关键账号开启登录告警,监控 Accepted 记录中的陌生 IP;用 lastb 与 fail2ban 统计每周复盘封禁来源;在边界层叠加主机入侵检测与统一策略管理,例如 AegisX 提供的登录审计与异常行为告警能力,可与 fail2ban 形成日志侧与主机侧的互补。SSH 安全不是一次性配置,而是密钥管理、封禁策略与审计告警的持续闭环。
常见问题(FAQ)
关闭密码登录后,本地电脑重装系统丢了私钥怎么办?
结论是提前准备带外救援通道。可通过云厂商VNC控制台或机房KVM登录,用root或其他sudo用户临时把PasswordAuthentication改回yes并重启sshd,登录后重新下发公钥再关闭密码。更稳妥的做法是保留一个备用密钥放在离线介质,并在authorized_keys中配置多把公钥,避免单点失效。
fail2ban封禁后为什么日志里还有大量失败记录?
结论是封禁只针对来源IP,已建立的连接和未触发阈值的IP仍会尝试。检查bantime与maxretry是否过松,确认banaction与系统防火墙一致(firewalld用firewallcmd-rich-rules,nftables用nftables-multiport),并用fail2ban-client status sshd查看当前封禁列表与命中次数。
只改SSH端口不装fail2ban够不够?
结论是不够,改端口只能减少扫描噪音。自动化爆破会做全端口扫描,端口变更后仍可能被找到。建议端口变更与密钥登录、fail2ban组合使用,并配合防火墙只放行可信来源,形成多层防护,而不是依赖单一手段。
fail2ban会不会误封自己或运维同事?
结论是可能,尤其是多人共用出口IP时。上线前把公司出口IP加入ignoreip白名单,先设较大maxretry与较短bantime观察几天,再逐步收紧。若被误封,用fail2ban-client set sshd unbanip 你的IP立即解封,并复查白名单配置。
如何确认服务器已经被爆破成功入侵?
结论是看成功登录记录与异常账户。用last和lastb对比成功与失败登录,检查/var/log/auth.log中Accepted记录是否有陌生IP,审计authorized_keys是否被追加未知公钥,排查新增UID 0账户、异常cron与开机自启项,发现可疑立即断网取证并更换全部密钥。