SSH 暴力破解攻击的真实面貌

解剖每台开放 22 端口的 Linux 服务器都会收到的流量:谁在发动、真正在尝试什么,以及哪些防御能降低流量而不是被动承受。

阅读约 7 分钟

用大白话说,这是什么

SSH 暴力破解并不是冲着您来的,而是一种批量作业:有人租一个僵尸网络,喂进 IP 段,让它对所有在 22 端口应答的机器尝试登录。用户名清单短小而乏味——root、admin、ubuntu、test、git、oracle、postgres,以及今年恰好流行的那些服务账户。

让它持续运转的是经济账。一台 Linux 机器上的 shell 值钱——可以挖矿、当代理、当作通向这台机器所能触及的一切的落脚点——而一次尝试几乎不花成本。把一台全新服务器放到公网 IP 上:第一次探测通常一小时内就到,一周后每天几千次失败毫不稀奇。

关键在量级。一个人猜您的密码是个轶事;每月十万次来自不断轮换地址的尝试是一种背景条件,而按前者设计的防御对后者毫无作用。

他们究竟在尝试什么

同一份日志里会出现三种不同的行为,应对方式也各不相同。

root 登录尝试最吵闹,也最不危险,因为任何配置正确的服务器都会把 PermitRootLogin 设为 no 或 prohibit-password。每天数千条这样的记录,说明机器人还没弄明白 root 不可用——它们永远也弄不明白,因为继续问下去对它们毫无成本。

接下来是用户名枚举:把常见账户名过一遍,找一个真实存在的。在现代 OpenSSH 上,过去让这招可靠的时间差已基本被消除,但机器人照样尝试,一旦命中就有了明确目标。

撞库才是真正会得手的那种。别人泄露库里的用户名密码对,拿到您的服务器上重放。它看起来是少量尝试而非洪水,并且在某个开发者复用了密码时就会成功。任何速率限制都拦不住它,因为根本没有速率可限。

SSH 有而其他协议没有的东西

SSH 有一条大多数暴露服务都没有的退路:公钥认证。彻底关闭密码认证,整类猜解攻击就不是变难,而是变得不可能——根本没有密码可猜。

这确实是可用手段中最强的一招,如果您能做到,本文其余部分都是次要的。它有专门的一篇指南。

但流量并不会因此停止。机器人不知道您的配置,它们继续连接、继续提交密码、继续被拒绝。每一次尝试依然消耗一个 TCP 连接、一次 sshd 分叉、一行日志和一小片 CPU,而您的认证日志依然轮转得足够快,足以丢掉您真正需要的事件。只用密钥消除的是风险,不是负载。

为什么只做速率限制不够

标准的第一答案是 fail2ban,这个答案是合理的——它在每个发行版的仓库里,而且确实管用。但在把它当作全部防御之前,值得先了解它的边界。

它封禁的是单个地址。僵尸网络会在一个网段里轮换:封掉 203.0.113.47,一小时后 .48 接上。封掉 /24 才能一次终结这一轮,而 fail2ban 开箱即用做不到这件事。

它的封禁会过期。默认值以分钟计,同一个僵尸网络今晚就回来。您可以调长,但状态存在内存和一个文件里,都挺不过重建。

它不会向别人学习。每台服务器都从零独立发现每个攻击者,代价是每次都要承受最初的 N 次尝试。

而且它会静默失效。发行版升级后不再匹配的正则、被软件包更新关掉的 jail、重启后没起来的服务——这些都不会主动报告,失效看起来和太平无事一模一样。

什么才真正降低流量

只有一件事能改变量级:拒绝与来源对话。其余所有做法都是在和它谈判。

这意味着盯住失败流,当某个来源越过阈值时,在 sshd 为它花费任何资源之前就在防火墙丢弃它。三个属性区分了扛得住的防御和会漏的防御:

  • 封禁子网,而不是地址。攻击流量来自托管商网段,相邻地址属于同一运营商;合法用户几乎不会和扫描器共用一个 /24。
  • 永久封禁,并挺过重启。规则必须落在 nftables 里并在开机时恢复,而不是待在某个守护进程的内存中。
  • 在启用任何东西之前先把自己加入白名单。这件事最常见的翻车方式,就是管理员把自己的地址挡在了一台只能通过 SSH 访问的服务器之外。

不用自己维护这套机制

SSH Protector 就是把这套逻辑打包成一个代理。它读取的正是您会去读的那条 journald 或 auth.log 流,在本地做判断——因此断网时仍然有效——并维护一个包含所有被封网段的合并 nftables 集合。

安装时,它从 sshd 配置中识别真实的 SSH 端口,而不是想当然认为是 22,并在封禁任何东西之前先把您当前连入的地址加入白名单。

您独自无法构建的部分是共享信誉:攻击过其他客户的地址在到达您这里之前就已被封禁,因此您永远不必承受它最初的 N 次尝试。一台服务器永久免费,足以让您在自己的机器上观察真实攻击流,凭证据而不是凭一篇文章来做决定。

FAQ

每天多少次 SSH 登录失败算正常?
在无法从公网访问的服务器上接近于零。在 22 端口对任意地址开放的服务器上,每天几千次毫不稀奇,也说明不了您有什么特别之处——那只是全网扫描的背景水平。真正重要的是趋势和来源分布,而不是绝对数字。
禁用 root 登录能阻止 SSH 暴力破解吗?
它能阻止对方在 root 上得手,这值得做,而且只是 sshd_config 里的一行。但它完全不会减少尝试量:机器人不知道 root 不可用,会无限期地继续尝试。请在禁用 root 登录的同时封禁来源,否则您仍要为每一次尝试付费。
只用 fail2ban 够吗?
对于一台您定期查看的服务器,它是合理的防御,也远好过什么都没有。它的实际边界是:面对轮换网段的僵尸网络只封单个地址;封禁会过期且挺不过重建;服务器之间没有共享知识;以及静默的失效方式——坏掉的 jail 看起来和太平的一周完全一样。
SSH 攻击该封禁整个 /24 子网吗?
对于刚刚向您投来数百次失败登录的网段,通常该封。攻击流量来自托管商和 VPS 网段,相邻地址属于同一运营商,而家庭用户几乎不会和扫描器共用一个 /24。把自己的办公地点和 VPN 出口保留在白名单里,误报率就接近于零。

在您自己的攻击流上看看效果

一台服务器,永久免费,无需信用卡。代理一分钟即可安装,并在封禁任何东西之前先把您当前的地址加入白名单。