
核心要点(TL;DR)
- SSH 被爆破先看 auth.log 与 lastb,确认攻击 IP、尝试次数和是否已有成功登录。
- fail2ban 用 jail.local 覆盖配置,maxretry=3、bantime 递增,避免改 jail.conf。
- 根治靠禁用密码登录改密钥认证,fail2ban 只是缓解层。
- 加固后必须用新会话验证再退出,防止把自己锁在服务器外。
凌晨收到 CPU 告警,登录服务器一看 /var/log/auth.log 里刷满 Failed password for root,几分钟上千条——这是绝大多数运维都遇到过的场景。SSH 暴露在公网,被自动化爆破只是时间问题。本文按「先确认现状、再止血、最后根治」的顺序,给出可直接复制执行的排查命令、fail2ban 配置与 sshd 加固清单,帮你在一小时内把风险压下去。
一、先确认:你的 SSH 到底被爆破到什么程度
不要急着改配置,先取证。不同发行版日志位置不同,先确认日志来源:
- Debian/Ubuntu:
/var/log/auth.log - CentOS/RHEL 7:
/var/log/secure - CentOS/RHEL 8+/systemd 系统:
journalctl -u sshd
统计失败登录来源 IP 与次数:
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20
查看失败登录汇总(需安装 psacct/acct 或直接读 btmp):
lastb | head -30
lastb | wc -l
最关键的一步是确认有没有被攻破:
grep "Accepted" /var/log/auth.log | tail -30
last -n 20
如果出现陌生 IP 的成功登录、陌生用户名,或 last 里有异常时间段的会话,说明已不是「被扫」而是「被入侵」,应立刻隔离主机、排查后门与计划任务(crontab -l、/etc/cron.*、~/.ssh/authorized_keys),再谈加固。
二、止血:fail2ban 安装与最小可用配置
fail2ban 通过读取认证日志,对短时间内多次失败的 IP 自动下发防火墙封禁,是应对 SSH 爆破成本最低的手段。
1. 安装
# Debian/Ubuntu
apt update && apt install -y fail2ban
# CentOS/RHEL
yum install -y epel-release && yum install -y fail2ban
2. 用 jail.local 覆盖默认配置
永远不要直接改 jail.conf,升级会被覆盖。新建 /etc/fail2ban/jail.local:
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
ignoreip = 127.0.0.1/8 你的办公固定IP
[sshd]
enabled = true
port = ssh
# CentOS/RHEL 8+ 或日志走 journal 时启用下一行
# backend = systemd
bantime = 86400
maxretry = 3
参数含义:findtime 内失败 maxretry 次即封禁 bantime 秒。生产环境建议首次封禁 1 天,配合 bantime.increment = true 让重复攻击者封禁时间递增。
3. 启动与验证
systemctl enable --now fail2ban
fail2ban-client status
fail2ban-client status sshd
输出中的 Currently banned 与 Banned IP list 能直接看到封禁效果。若 Currently failed 长期为 0 而日志里明明有失败记录,多半是日志路径或 backend 配错,按上文切换 backend = systemd 后 fail2ban-client reload。
注意:fail2ban 依赖本机防火墙下发规则。若使用云厂商安全组且未启用 iptables/nftables,封禁可能不生效,需确认 iptables -L -n 中存在 f2b 链。
三、根治:sshd_config 加固与密钥登录
fail2ban 只能降低攻击频率,真正的防线是让密码登录这条路走不通。编辑 /etc/ssh/sshd_config:
| 配置项 | 建议值 | 作用 |
|---|---|---|
| PermitRootLogin | no | 禁止 root 直接登录,改用普通用户 + sudo |
| PasswordAuthentication | no | 关闭密码认证,仅允许密钥 |
| PubkeyAuthentication | yes | 启用公钥认证 |
| MaxAuthTries | 3 | 降低单连接尝试次数 |
| LoginGraceTime | 30 | 缩短未认证连接占用时间 |
| AllowUsers | 指定运维账号 | 白名单化可登录用户 |
操作顺序极其重要,避免把自己锁在门外:
- 先在本机生成密钥并上传:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server - 新开一个终端验证密钥登录成功,不要关闭当前会话
- 再修改
sshd_config,执行sshd -t检查语法 systemctl reload sshd重载,仍保留旧会话- 新会话再次验证,确认无误后再退出旧会话
如需调整端口,修改 Port 22 为高位端口并同步放行防火墙与云安全组,注意 SELinux 环境需执行 semanage port -a -t ssh_port_t -p tcp 新端口。
四、加固后验收清单
- ☐
fail2ban-client status sshd显示已封禁 IP - ☐
sshd -T | grep -E "passwordauth|permitrootlogin"输出均为 no - ☐ 新终端密钥登录成功,密码登录被拒绝
- ☐
lastb失败记录不再暴涨,或已被快速封禁 - ☐ 云安全组仅放行必要来源 IP
- ☐ 已配置日志告警,异常登录可第一时间通知
在主机层之外,建议叠加网络层的入侵防护能力,例如 AegisX 提供的暴力破解检测与自动封禁策略,可在 SSH 之外统一覆盖 Web、数据库等暴露面,减少逐台维护 fail2ban 规则的负担。
五、行动建议
今天就做三件事:第一,跑一遍第一节的日志统计命令,确认是否已被攻破;第二,装上 fail2ban 并用 jail.local 配置 maxretry=3、bantime=86400;第三,用密钥登录替换密码登录并禁用 root 直连。三步完成后,SSH 爆破日志会在几天内显著下降,服务器暴露面也随之收敛。
常见问题(FAQ)
怎么快速判断 SSH 是不是正在被暴力破解?
看失败登录频率即可判断。执行 grep "Failed password" /var/log/auth.log | tail -n 20,若短时间内出现大量来自陌生 IP 的失败记录,或用 lastb 看到成百上千条失败登录,就是典型爆破。再用 grep "Accepted password" 确认是否有异常成功登录,有则按入侵事件处理。
fail2ban 和改 SSH 端口哪个更有效?
两者定位不同,fail2ban 更关键。改端口只能挡住扫描器,针对性爆破照样能打进来;fail2ban 能根据日志自动封禁高频失败 IP,直接削减攻击量。最佳实践是禁用密码登录改用密钥,再叠加 fail2ban 与端口调整,形成多层防护。
配置 fail2ban 后为什么没有生效?
多数是日志路径或后端不匹配。Debian/Ubuntu 用 /var/log/auth.log,CentOS/RHEL 8+ 用 systemd 后端读 journal,需在 jail.local 中设置 backend = systemd。改完执行 fail2ban-client status sshd 查看当前封禁数与日志匹配情况,再 fail2ban-client reload 重载。
误封了自己的 IP 怎么解封?
用 fail2ban-client 直接解封。先 fail2ban-client status sshd 查看 Banned IP list,再执行 fail2ban-client set sshd unbanip 你的IP。若已无法登录,可通过云控制台 VNC 或救援模式进入,编辑 jail.local 把本机 IP 加入 ignoreip,然后重启 fail2ban 服务。
只做 fail2ban 不做密钥登录够安全吗?
不够。fail2ban 只是缓解层,弱口令一旦被低频慢速爆破命中仍会失守。应同时修改 sshd_config:PasswordAuthentication no、PermitRootLogin no、限制 AllowUsers,并配合密钥登录与 sudo 提权。这样即使密码泄露,攻击者也无法直接登录。