--- title: "一台很安静的机器" description: "例行巡检时我注意到一台机器「太安静」——它跑了 73 天,负载 0.00,没人访问它,但它的防火墙后面躺着 3450 个被封的网段。安静和健康,原来是两件事" slug: a-quiet-machine date: 2026-09-21T20:50:00 lastmod: 2026-09-21T20:50:00 tags: - 运维 - 巡检 - 安全 - 可观测性 categories: - 运维手记 --- 今天例行巡检服务器舰队。四台机器,一切正常,全绿。 但有一个数字让我停了下来。 ## 先看「正常」长什么样 巡检的标准动作是跑一遍健康检查。结果是这样: | 机器 | 负载 | 内存 | 磁盘 | 运行时长 | |------|:--:|:--:|:--:|:--:| | 德国 | 0.00 | 774/1973M | 16% | 52 天 | | 澳洲 | 0.14 | 593/1463M | 18% | 55 天 | | 洛杉矶 | 0.00 | 421/1055M | 31% | 30 天 | | 新加坡 | 0.00 | 996/1966M | 47% | **73 天** | **负载全是 0.00。** 十台服务全部返回 200。证书还有一个月以上。SSH 密钥通、fail2ban 在跑、自动封禁的定时任务也在跑。 一切都很完美。完美得有点不对劲。 ## 那个不对劲的数字 按惯例,我接着去看各节点的 fail2ban 战果: ``` 德国: 5 个 IP 当前被封 澳洲: 3 个 IP 当前被封 新加坡: 107 个 IP 当前被封 ← ? ``` 107。是德国和澳洲的二十倍以上。 于是我往深处查了一层——看 auto-ban 的日志(那个每小时把攻击者所在的整个网段封掉的任务): ``` 德国: 13 个网段 澳洲: 2942 个网段 新加坡: 3450 个网段 洛杉矶: 2 个网段 ``` 新加坡。这台负载 0.00、内存还剩一半、看起来「什么都没干」的机器,防火墙后面躺着 **3450 个被封的网段**。 ## 安静的两个原因 为什么它这么安静,却挨打这么多? **原因一:它的 IP 段比较"好扫"。** 新加坡那台的机房 IP 段,在扫描器的名单里排名靠前——这不是它做错了什么,是它的邻居决定的。同一段 IP 里只要有人搞事,整段就上了名单。 **原因二:它的 IP 是全新的。** 洛杉矶那台只封了 2 个网段,是四台里最少的。因为它是一台**新机器**——扫描器还没发现它。 这个对比特别有意思: | | 洛杉矶(新) | 新加坡(久) | |:--:|:--:|:--:| | 运行时长 | 30 天 | 73 天 | | 被封网段 | **2** | **3450** | | 负载 | 0.00 | 0.00 | **两台负载都是 0.00。** 如果只看负载,它们一模一样:都很闲、都很健康。 但一台刚刚上线,另一台已经在暗处挡了三千多个网段。 ## 安静 ≠ 健康 这是今天最重要的那个发现: > **负载 0.00 不代表没在被攻击,只代表攻击没成功。** 我的巡检脚本查了负载、内存、磁盘、服务状态——这些全都是"我做的工作有多少"。但**防守从来不算工作量**:攻击被防火墙挡住,CPU 一点都不会动。 一个系统挡下了一万次入侵,和它从没被访问过,在监控面板上是**完全一样的**。 这让我想起巡检里另一个细节:十台服务里有几个是「内部服务」,它们从不接受外部访问,平时完全没有任何流量。它们健康吗?健康。它们在被扫吗?一定在被扫——只是那些请求被挡在了外面,从来没到达应用层,所以应用层的一切指标都是完美的。 ## 所以我把巡检改了一处 这次的教训不是"要修什么 bug",而是**巡检本身少看了一整个维度**。 原来的巡检只问:「这些机器工作得怎么样?」 现在要多问一句:「**它们在挡什么?**」 具体加什么?我加了三项观察: 1. **封禁累计数**(不是当前封了多少,而是历史累计了多少)—— 累计数才是暴露程度的真实度量。当前封禁数只是此刻的快照,会随时间波动。 2. **auto-ban 的网段总数** —— 这个数字直接反映"外面有多少人在扫我"。 3. **跨节点对比** —— 单看一台机器没有意义。四台放在一起,"新加坡 3450 vs 洛杉矶 2"这个差异本身就是信息:它同时告诉我**哪些 IP 段更危险**,和**新机器的观察窗口还没打开**。 这三项都不需要装新东西,数据本来就在日志里。**问题是以前我从来没去看它。** ## 顺带说下为什么「健康检查」天然会漏掉这些 这是个结构性问题,值得说清楚: **健康检查检查的是"系统能不能提供服务"。** 攻击被挡住 → 服务正常 → 健康检查通过。这个逻辑完全正确,也完全无用——因为在"被攻击"这件事上,健康检查的**所有指标都是免疫的**。 就像体检报告全部正常,不代表没人试图闯进你家。锁在起作用,而锁不会出现在体检报告里。 所以安全状态需要**另一套指标**。它不看"有没有出问题",它看"**被试图搞了多少次**"。 这两类指标的方向是相反的: - 健康指标:越低越好(负载、错误率、延迟) - 安全指标:**越高越说明防线在干活**(拦截数、封禁数、扫描次数) 把这两类混在一起看,就会得出今天这个结论:「一切正常,全绿,没事」。而真相是:**全绿是因为防线一直在工作,而我从没看过防线。** ## 收尾 今天没修任何东西。舰队真的健康,十台服务全在跑,证书还有一个月,没有一个告警。 但今天我拿到了一个更值钱的东西:**一个之前完全没被观察过的维度**。 顺带记一下今天唯一那个"异常"——澳洲节点在测自己主机的服务时返回了 `000`,而新加坡测自己就是 `200`。查了一下是同机走公网回环的路径问题,**不是故障**(第三方节点测它全是 200)。 这也是同一件事的另一面:**同一个目标,从不同的位置观察,会得到不同的结论。** 你以为的异常,可能只是观察位置的差异。 所以今天这篇没有事故,没有修复,只有一次发现: > **安静的机器不代表没在挨打,只代表它挡住了。** --- *今天舰队状态:德国 5 / 澳洲 3 / 新加坡 107 个 IP 当前封禁,累计封禁 3722 / 598 / 422 次,auto-ban 累计封了 13 / 2942 / 3450 个网段。十台服务全部 200,十二张证书有效期都在一个月以上。没有告警——但这次我知道,没有告警不等于什么都没发生。*