SSH 被暴力破解之后:3 分钟定位、再用 fail2ban 自动封禁
凌晨两点的那条告警
手机弹出一条云监控告警:某台服务器 SSH 连接数异常。第二天早上打开 auth.log,密密麻麻的 Failed password,来自五六个不同网段,每秒两三次,持续了整整一夜。
这不是偶然。任何一台把 22 端口暴露在公网的服务器,上线几个小时之内就会被扫描器找到 —— 全球有大量自动化脚本在 24 小时轮询全网段。所以问题从来不是“会不会被扫到”,而是“被扫到之后你做了什么”。
这篇文章给一套完整且可复用的处置流程:先看规模、再看是谁在敲门、然后确认到底有没有被攻破,最后用 fail2ban 把重复敲门的 IP 自动挡在门外,并把入口本身收窄。
一、先看规模:到底被撞了多少次
不同发行版的日志位置不完全一样:
· Debian / Ubuntu:/var/log/auth.log
· CentOS / openEuler 等:/var/log/secure
· 用 systemd-journald 统一收口的系统:直接用 journalctl
最直接的一行命令是统计失败次数:
grep -c "Failed password" /var/log/auth.log
如果是 CentOS 系,换成 /var/log/secure。数字上千很常见,几万也不算异常。
更实用的是按 IP 聚合,看谁撞得最凶:
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20
这里要根据日志格式微调字段位置:有的发行版 IP 在倒数第四个字段,有的在倒数第三个。拿不准就先 head -3 看一条样本,再决定 awk 取哪一列。输出就是“次数 + IP”的排行,前几名往往占了绝大部分请求。
如果日志已经被 logrotate 轮转过,或者你想跨天看,用 journalctl 更方便:
journalctl -u ssh -u sshd --since "2026-11-01" --until "2026-11-12" | grep -c "Failed password"
服务名在 Debian/Ubuntu 上是 ssh,在 RHEL 系上是 sshd,两个都写上不会报错,找不到的那个直接跳过。
还有一个更快的入口:lastb。它读的是失败的登录记录:
lastb | head -30 lastb | wc -l
如果 lastb 一直输出到不停,说明量已经到了需要马上处理的级别。
二、看“谁在敲门”:IP、用户名与节奏
聚合完之后,再看两个维度。
第一个是用什么用户名在试:
grep "Failed password" /var/log/auth.log | sed 's/.*for /for /' | awk '{print $2}' | sort | uniq -c | sort -rn | head
常见结果会是 root、admin、test、ubuntu、oracle、postgres 这一串 —— 都是脚本里的常见字典。如果列表里出现了你自己真实使用的普通用户名,说明对方不只是乱扫,而是做过一点信息收集,这就值得警惕了。
第二个是节奏。同一个 IP 每秒试两次、连续试一周,是典型的自动化爆破;而每天只试三五次、换不同 IP,更像分布式的慢速尝试,目的是绕开基于频率的封禁策略。前者 fail2ban 一下就挡住了,后者需要把观察窗口拉长,后面配置里会提到 findtime 怎么调。
三、最关键的一步:确认有没有被攻破
还没确认是否被登进来之前,不要先急着封 IP。先查成功登录的记录:
grep "Accepted" /var/log/auth.log | tail -30 journalctl -u ssh -u sshd | grep "Accepted" | tail -30
正常情况下应该只有你自己的 IP,而且是你记忆里的时间点。出现陌生 IP 就是红线。
再用 last 看成功登录历史,包括已经退出的会话:
last -a | head -30
last 会把“谁、从哪个 IP、什么时间、登了多久”列出来。注意 last 可能被攻击者篡改(wtmp 可写),所以它只能作为参考,不能作为唯一依据。
然后看当前在线会话与连接:
who w ss -tnp | grep -E ':22|:2222'
前两个看你自己的登录会话,第三个看当前所有到 SSH 端口的连接及其对应进程。如果某个 PID 不是你熟悉的 sshd 会话,就要进一步查。
接下来是三个高频持久化位置,建议被扫之后无条件都查一遍:
cat ~/.ssh/authorized_keys crontab -l ls -la /etc/cron.d/ /etc/cron.daily/ ps aux --sort=-%cpu | head
authorized_keys 里出现陌生公钥,或者 crontab 里多了个不明脚本,都是被入侵的典型痕迹。前者往往就是攻击者留下的“后门钥匙”,后者一般是挖矿程序用来保活的。
如果这几处都是干净的,也没有陌生 Accepted 记录,那么大概率只是被扫、没被进。真正的处置重点就转到了“防”:让它继续扫也不能得手。
四、封禁:三分钟让 fail2ban 上线
确认没被进去之后,就该让平台自己干活了。fail2ban 的思路很简单:盯住日志,同一 IP 在时间窗口内失败太多就自动加防火墙规则,过期自动解开。
装:(Debian/Ubuntu 或 RHEL 系二选一)
apt install -y fail2ban # 或 dnf install -y fail2ban
不要直接改 jail.conf,那会在升级时被覆盖。新建 /etc/fail2ban/jail.local:
[DEFAULT] ignoreip = 127.0.0.1/8 ::1 你的办公网出口IP bantime = 6h findtime = 10m maxretry = 5 backend = systemd [sshd] enabled = true port = ssh filter = sshd maxretry = 5
四个参数的含义值得讲清楚:
· findtime 是观察窗口。设得太短,慢速分布式破解就手感了;设成 10 分钟是个折中值。如果你观察到对方是“每小时试两次”那种慢节奏,把窗口拉到 1h 以上才有意义。
· maxretry 是窗口内允许的失败次数。5 次对正常人工登录足够宽容,对手术脚本则一碰就触发。
· bantime 是封禁时长。6h 是常见值;纯公网业务机器可以拉长到 24h 到 1w,代价是误封恢复慢。
· ignoreip 一定要写自己的固定出口 IP。这是最容易踩的坑:没有白名单,自己连续输错几次密码就把自己封在外面了,而这时你唯一的恢复手段就是控制台 VNC。
改完之后启用并验证:
systemctl enable --now fail2ban systemctl status fail2ban fail2ban-client status sshd
最后一条命令会输出当前被监测的日志路径、已封禁 IP 列表和总数。刚怀疑的“是不是没生效”看着这个就知道:如果还在封禁列表里,说明确实又撞进来了。手动解封某个 IP:
fail2ban-client set sshd unbanip 1.2.3.4
如果 fail2ban 启动报 “unable to read /var/log/auth.log”,通常是 systemd backend 与路径不匹配,改成 backend = auto 或指向具体日志文件即可。
五、再加一层:把入口本身收窄
fail2ban 是“事后封”,真正减少噪静的办法是让门根本不好敲。下面四件事按性价比排序:
第一,用云安全组或防火墙限制来源。这是最有效的一层:如果只有你固定的办公 IP 需要连,直接在安全组只放行那个网段,22 端口对公网完全不对。扫描器就算扫到端口开放,也建不了连接。
第二,改端口。把 22 改成 2222 或更高位端口,本质上只是“降低被扫到的概率”,并不增加安全性,但能瞬间滤掉绝大多数只会敲 22 的脚本。改了之后记得同步安全组、fail2ban 的 port 字段和你的 SSH config。
第三,禁止 root 直接登录,并关掉密码认证:
# /etc/ssh/sshd_config PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes MaxAuthTries 3
关掉密码认证之后,字典爆破直接失效 —— 攻击者猜对密码也没用,因为根本不验密码。这一步的依赖是:你必须先把公钥放好、用密钥能成功登录,否则一旦 reload 就彻底进不去了。
第四,如果机器上就一两个运维账号,直接限定名单:
AllowUsers deploy opsadmin
名单之外的用户名连尝试都没资格,日志也会干净很多。
改完 sshd 配置后,正确的验证姿势是:不要 reload 完就关掉当前会话。重新开一个终端窗口试登录,确认新会话能进,再把旧窗口关掉。sshd 支持热加载:
sshd -t systemctl reload sshd
sshd -t 先做语法检查,能挡掉绝大多数“配置写错导致全部登录失败”的惨案。
六、小结:一套可以贴在便签上的顺序
1. 看规模:grep -c 加按 IP 聚合,先知道自己面对的是小打小闹还是一波流量。
2. 查成功登录:Accepted 记录 + last + who,确认到底有没有人进来过。
3. 查持久化:authorized_keys、crontab、异常进程,三处干净才敢说“只是被扫”。
4. 封:fail2ban 上线,白名单先行,窗口和封禁时长按实际节奏调。
5. 收窄:安全组 → 改端口 → 禁 root + 关密码 → 收窄用户名单。
最后提醒两个常见误区:一是“内网机器不用管”,实际上跳板机往往就是从内网横向过去的;二是“装完 fail2ban 就万事大吉”,它只处理 SSH 一类日志,如果是 Web 层的喷洒或 API 爆破,得单独配 jail。
被扫不是事故,被扫了几个月一直不知道才是。把日志看一眼、把 fail2ban 装一下,成本不到半小时,换的是后面一整年的安静。
- 点赞
- 收藏
- 关注作者
评论(0)