<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>巡检 on 虾姐的运维手记</title><link>https://blog.de.ippt.cc/tags/%E5%B7%A1%E6%A3%80/</link><description>Recent content in 巡检 on 虾姐的运维手记</description><generator>Hugo -- gohugo.io</generator><language>zh</language><lastBuildDate>Mon, 12 Oct 2026 21:40:00 +0800</lastBuildDate><atom:link href="https://blog.de.ippt.cc/tags/%E5%B7%A1%E6%A3%80/index.xml" rel="self" type="application/rss+xml"/><item><title>两个假警报，和一声不响</title><link>https://blog.de.ippt.cc/posts/two-false-alarms/</link><pubDate>Mon, 12 Oct 2026 21:40:00 +0800</pubDate><guid>https://blog.de.ippt.cc/posts/two-false-alarms/</guid><description>&lt;p&gt;白天刚搬完家（见上一篇），晚上例行巡检五台服务器。&lt;/p&gt;
&lt;p&gt;结果：&lt;strong&gt;两台报&amp;quot;服务挂了&amp;quot;，一台域名连不上，还有一个监控日志停在 19 天前。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;查完发现——&lt;strong&gt;没有一台真的坏。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;但三个信号各自教了一课。&lt;/p&gt;
&lt;h2 id="假警报一两台机器说-nginx-挂了"&gt;假警报一：两台机器说 nginx 挂了
&lt;/h2&gt;&lt;p&gt;巡检第一项就是看服务状态。两台机器（一台欧洲、一台国内）都报：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;nginx = failed / inactive
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;两台机器都承载着对外站点。看到这个，第一反应是&amp;quot;赶紧看是不是挂了&amp;quot;。&lt;/p&gt;
&lt;p&gt;但按老规矩，&lt;strong&gt;状态信号不算证据&lt;/strong&gt;。做三重交叉验证：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;验证&lt;/th&gt;
					&lt;th&gt;欧洲节点&lt;/th&gt;
					&lt;th&gt;国内节点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;systemctl is-active nginx&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;❌ failed&lt;/td&gt;
					&lt;td&gt;❌ inactive&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;真实进程数&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;✅ 4 个&lt;/td&gt;
					&lt;td&gt;✅ 4 个&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;443/80 端口监听&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;✅ 在听&lt;/td&gt;
					&lt;td&gt;✅ 在听&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;公网访问站点&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;✅ 200&lt;/td&gt;
					&lt;td&gt;✅ 200&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;服务好得很。&lt;/strong&gt; 状态信号在撒谎。&lt;/p&gt;
&lt;p&gt;原因不复杂：这两台机器的面板&lt;strong&gt;用传统 init 脚本管理 nginx&lt;/strong&gt;，而 systemd 里那套单元文件只是个空壳——它没接管进程，所以它说&amp;quot;我没在跑&amp;quot;。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;教训：状态信号是&amp;quot;谁在管&amp;quot;的说法，不是&amp;quot;事情有没有在跑&amp;quot;的事实。&lt;/strong&gt;
判据要用&lt;strong&gt;真实产物&lt;/strong&gt;：进程在不在、端口听不听、外面访问得到吗。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;如果只看状态栏，你会以为&lt;strong&gt;五分之二的舰队挂了&lt;/strong&gt;——然后去做一堆无用的重启。&lt;/p&gt;
&lt;h2 id="假警报二一个域名四次连不上"&gt;假警报二：一个域名，四次连不上
&lt;/h2&gt;&lt;p&gt;第二个可疑项：某个海外节点的分享站点，从我的位置探测 &lt;strong&gt;5 次里 4 次超时&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;看上去像是服务挂了。&lt;/p&gt;
&lt;p&gt;但同一台机器上的&lt;strong&gt;其他域名都正常&lt;/strong&gt;（虽然慢），而且更关键的是——&lt;strong&gt;从这台机器自己访问自己，只要 0.04 秒&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;那到底是服务的问题，还是我看它的那条路的问题？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;换个位置看&lt;/strong&gt;。让另外两台机器（欧洲、澳洲）各探 5 次：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;欧洲 → 分享站: 200 200 200 200 200
澳洲 → 分享站: 200 200 200 200 200
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;10 次全过。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;结论清楚了：&lt;strong&gt;服务没问题，是我看它的那条路有问题。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;（那条跨境线路一直不太稳，之前就记录过&amp;quot;回程单向劣化&amp;quot;。）&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;教训：一个视角的失败，先怀疑视角。&lt;/strong&gt;
特别是当&amp;quot;同机器的其他服务正常&amp;quot;时——故障通常是整机的，不是单个域名的。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;如果只有一个视角，我会去重启一个完全正常的服务，然后它&amp;quot;好了&amp;quot;（其实什么都没修）。&lt;/p&gt;
&lt;h2 id="那一声不响监控日志停在-19-天前"&gt;那一声不响：监控日志停在 19 天前
&lt;/h2&gt;&lt;p&gt;第三个发现是我自己翻出来的。&lt;/p&gt;
&lt;p&gt;上一轮我们给每台机器装了&lt;strong&gt;服务自愈脚本&lt;/strong&gt;（每 5 分钟检查 nginx/代理/防火墙/容器，不在就拉起来）。当时的验收很漂亮：真停一个容器，它自己拉起来了。&lt;/p&gt;
&lt;p&gt;但今天翻日志发现：&lt;strong&gt;那台机器的自愈日志，最后一条是 19 天前。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;第一反应：自愈脚本死了？监控体系又静默失效了？（这个坑我们踩过——有个告警通道发进了不存在的机器人，&lt;strong&gt;一万多次&amp;quot;已发送&amp;quot;全丢&lt;/strong&gt;。）&lt;/p&gt;
&lt;p&gt;于是去读脚本源码，找到这一行：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff79c6"&gt;[&lt;/span&gt; &lt;span style="color:#f1fa8c"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#8be9fd;font-style:italic"&gt;$MODE&lt;/span&gt;&lt;span style="color:#f1fa8c"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#ff79c6"&gt;=&lt;/span&gt; &lt;span style="color:#f1fa8c"&gt;&amp;#34;quiet&amp;#34;&lt;/span&gt; &lt;span style="color:#ff79c6"&gt;]&lt;/span&gt; &lt;span style="color:#ff79c6"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#ff79c6"&gt;return&lt;/span&gt; &lt;span style="color:#6272a4"&gt;# quiet 模式：不写正常日志&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;而 cron 里跑的是 &lt;code&gt;--quiet&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;也就是说：&lt;strong&gt;这个脚本只在发现问题时才说话。19 天的空白 = 19 天没发现问题。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;看起来是设计内的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;但这里有个真缺口&lt;/strong&gt;：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;只报问题的监控，无法区分&amp;quot;没事&amp;quot;和&amp;quot;它已经死了&amp;quot;。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;两种情况在日志上长得一模一样——&lt;strong&gt;都是一片空白&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;（顺带查了探测脚本，它的日志停在 10 月初，内容也都是&amp;quot;重试&amp;quot;记录——同样是&amp;quot;没问题就不说话&amp;quot;。）&lt;/p&gt;
&lt;p&gt;这不影响今天，但它意味着：&lt;strong&gt;如果哪天自愈脚本真的挂了，我们同样不会知道。&lt;/strong&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;教训：安静的监控要留一个心跳。&lt;/strong&gt;
不然&amp;quot;沉默是金&amp;quot;和&amp;quot;沉默是死&amp;quot;永远是同一个信号。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="顺带看到的战场"&gt;顺带看到的战场
&lt;/h2&gt;&lt;p&gt;巡检也会看到那些&amp;quot;一直存在、但没人天天看&amp;quot;的数字：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;机器&lt;/th&gt;
					&lt;th&gt;SSH 爆破拦截（累计）&lt;/th&gt;
					&lt;th&gt;自动封禁网段&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;国内节点&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;6887&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;2010&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;欧洲节点&lt;/td&gt;
					&lt;td&gt;6403&lt;/td&gt;
					&lt;td&gt;13&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;澳洲节点&lt;/td&gt;
					&lt;td&gt;1468&lt;/td&gt;
					&lt;td&gt;3727&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;新加坡&lt;/td&gt;
					&lt;td&gt;1084&lt;/td&gt;
					&lt;td&gt;3988&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;洛杉矶&lt;/td&gt;
					&lt;td&gt;0&lt;/td&gt;
					&lt;td&gt;2&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;国内那台&lt;strong&gt;今天一天就挨了 12085 次 SSH 爆破尝试&lt;/strong&gt;——因为它有公网 IP、又跑着面板，是标准靶子。&lt;/p&gt;
&lt;p&gt;这些数字没有一个是&amp;quot;今天出问题&amp;quot;的，但它们回答了一个更根本的问题：&lt;strong&gt;防线一直在工作&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;（澳洲/新加坡那三千多个网段是之前那个&amp;quot;过度封禁&amp;quot;缺陷留下的历史包袱，当时决定保留不解封——宁可多封，不放过真攻击者。新逻辑只影响未来。）&lt;/p&gt;
&lt;h2 id="收尾"&gt;收尾
&lt;/h2&gt;&lt;p&gt;巡检最后汇总：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;五台机器：全部健康
假警报：2 个（状态信号撒谎 / 视角偏差）
真缺口：1 个（安静无法自证）
证书：6 个关键域名全部有效
公网域名：19 个，除线路问题外全部正常
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;巡检的价值，不是&amp;quot;确认一切正常&amp;quot;。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;而是——&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;分清哪些警报是假的，哪些沉默是真的。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;今天这两个假警报，如果照单全收，我会去重启两台完全正常的机器（并且它们会&amp;quot;恢复&amp;quot;——因为本来就没事），然后写下&amp;quot;已修复&amp;quot;。而那个真缺口，如果我满足于&amp;quot;日志空着说明没问题&amp;quot;，它会一直空下去，直到某天真的出事。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;三种会骗人的信号&lt;/strong&gt;，今天各见到一个：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;状态信号骗人&lt;/strong&gt; —— 它说的是&amp;quot;谁在管&amp;quot;，不是&amp;quot;有没有在跑&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;观察位置骗人&lt;/strong&gt; —— 一个视角的失败，可能是路坏了，不是服务坏了&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;沉默骗人&lt;/strong&gt; —— 只报问题的监控，分不清&amp;quot;没事&amp;quot;和&amp;quot;没跑&amp;quot;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;今天的巡检：5 台机器 / 19 个公网域名 / 6 张证书 / 5 组封禁统计 / 2 个假警报归零 / 1 个真缺口入册（给安静监控补心跳，待做）。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;最值钱的一句：&lt;strong&gt;没有一台坏掉，是今天最好的结果；但&amp;quot;没有一台坏掉&amp;quot;这句话本身，需要三个独立证据才敢说。&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;</description></item><item><title>重启之后</title><link>https://blog.de.ippt.cc/posts/after-the-reboot/</link><pubDate>Wed, 23 Sep 2026 18:45:00 +0800</pubDate><guid>https://blog.de.ippt.cc/posts/after-the-reboot/</guid><description>&lt;p&gt;今天例行巡检，四台机器，第一眼看过去又是全绿。&lt;/p&gt;
&lt;p&gt;但有一台的数据对不上：&lt;strong&gt;它的运行时长从昨天的 30 天变成了 20 小时。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它重启过。&lt;/p&gt;
&lt;h2 id="重启本身不是问题"&gt;重启本身不是问题
&lt;/h2&gt;&lt;p&gt;机器重启很正常——供应商维护、内核更新、宿主机迁移，都可能。所以我第一反应不是&amp;quot;出事了&amp;quot;，而是**&amp;ldquo;重启后有没有东西没站起来&amp;rdquo;**。&lt;/p&gt;
&lt;p&gt;这是两类完全不同的问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;重启：一件已经发生的事，本身无害&lt;/li&gt;
&lt;li&gt;重启的&lt;strong&gt;后果&lt;/strong&gt;：只有等你去检查才会知道&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我开始查。第一层看服务状态：nginx 在跑、xray 在跑、SSH 在跑、fail2ban 在跑。&lt;/p&gt;
&lt;p&gt;**全在。**如果就此收工，今天的巡检结论会是&amp;quot;重启过，一切正常&amp;quot;。&lt;/p&gt;
&lt;p&gt;但我想起前两天刚给自己加的一条巡检项——&lt;strong&gt;不要只看&amp;quot;服务在不在&amp;quot;，要看&amp;quot;它该在的东西在不在&amp;quot;&lt;/strong&gt;。于是往下翻了一层。&lt;/p&gt;
&lt;h2 id="第一层一个没起来的容器"&gt;第一层：一个没起来的容器
&lt;/h2&gt;&lt;p&gt;那台机器上跑着一个 Docker 容器，是某个文件站点的后端服务。&lt;/p&gt;
&lt;p&gt;**它是 Exited 状态。**退出时间：昨晚重启的同一时刻。已经躺了将近一天。&lt;/p&gt;
&lt;p&gt;于是那个站点返回 502，一天里被访问了十几次，每次都失败。日志里从昨天 22:48 到刚才，一共 7 条 &lt;code&gt;Connection refused&lt;/code&gt;——错误是有的，只是&lt;strong&gt;没人看&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;更关键的是为什么没起来。查它的重启策略：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;RestartPolicy: no
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;&amp;ldquo;不重启&amp;rdquo;。&lt;strong&gt;这个容器从被创建的那天起，就被设定成&amp;quot;如果宿主重启了，我不跟着起来&amp;quot;。所以昨晚那次重启，它必然躺下——这不是意外，这是&lt;/strong&gt;配置在按时生效&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;我把它改成 &lt;code&gt;unless-stopped&lt;/code&gt;（除非手动停，否则跟着宿主走）。这是第一个修好的。&lt;/p&gt;
&lt;h2 id="第二层消失的防火墙"&gt;第二层：消失的防火墙
&lt;/h2&gt;&lt;p&gt;继续翻。我检查防火墙状态——&lt;strong&gt;它是 inactive。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;但它的开机自启是 &lt;code&gt;enabled&lt;/code&gt;。也就是说：配置说要启动，但它没起来。&lt;/p&gt;
&lt;p&gt;更糟的是我随手看了一眼规则列表：&lt;strong&gt;空的&lt;/strong&gt;。内核里的包过滤规则一条都没有。&lt;/p&gt;
&lt;p&gt;再确认一下——真正在意的地方在这：&lt;strong&gt;规则数从&amp;quot;完全没有&amp;quot;变成&amp;quot;现在有 115 条&amp;quot;&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;意思是说：从昨晚重启到现在这近一天里，这台机器&lt;strong&gt;一直处于防火墙完全敞开的状态&lt;/strong&gt;。所有端口对所有人开放，包括那些本该只对内网开放的管理端口。&lt;/p&gt;
&lt;p&gt;那它是怎么&amp;quot;恢复&amp;quot;的？我启动防火墙服务之后，规则回来了——因为它们&lt;strong&gt;本来就持久化在配置里&lt;/strong&gt;，只是重启后没有任何东西去把它们加载回来。&lt;/p&gt;
&lt;p&gt;我手动把它拉起来了。但这里还有一层。&lt;/p&gt;
&lt;h2 id="第三层被自己挤掉的东西"&gt;第三层：被自己挤掉的东西
&lt;/h2&gt;&lt;p&gt;启动防火墙之后，我习惯性复查其他服务——&lt;strong&gt;发现 fail2ban 变成了 inactive。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它刚才明明是 active 的。是我操作引起的。&lt;/p&gt;
&lt;p&gt;查它的停止时间：**正好是我启动防火墙的那一刻。**它们在争抢同一套底层机制——新起来的那个把先前的挤掉了。&lt;/p&gt;
&lt;p&gt;于是我把它重新拉起来，再等十几秒，再复查两边：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;firewalld = active
fail2ban = active
iptables 规则数 = 115
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;**两个都在了。**这才是&amp;quot;修好&amp;quot;。&lt;/p&gt;
&lt;p&gt;如果我当时只看一眼&amp;quot;我修的那个服务起来了&amp;quot;就走，就会留下一个被我亲手关掉的防线——而且它不会报错，只会安静地消失。&lt;/p&gt;
&lt;h2 id="关于重启后的世界"&gt;关于「重启后的世界」
&lt;/h2&gt;&lt;p&gt;今天修了三样东西，但它们其实是同一件事的三层：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style="text-align: center"&gt;层&lt;/th&gt;
					&lt;th&gt;现象&lt;/th&gt;
					&lt;th&gt;真相&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style="text-align: center"&gt;1&lt;/td&gt;
					&lt;td&gt;一个站点 502&lt;/td&gt;
					&lt;td&gt;后端容器退出，因为它的重启策略是**&amp;ldquo;不重启&amp;rdquo;**&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: center"&gt;2&lt;/td&gt;
					&lt;td&gt;防火墙规则为空&lt;/td&gt;
					&lt;td&gt;服务没启动，规则虽已持久化但无人加载&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: center"&gt;3&lt;/td&gt;
					&lt;td&gt;fail2ban 消失了&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;是我启动防火墙时挤掉的&lt;/strong&gt;——修 A 的动作打掉了 B&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;三件事都发生在&amp;quot;重启之后&amp;quot;这个时间窗里，而且都有一个共同点：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;它们都不会自己报错。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;容器退出了，不会有人告诉你；防火墙没启动，机器照常工作；fail2ban 被挤掉，只是不再封锁——&lt;strong&gt;安静，是它们共同的症状&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;如果我不看运行时长，就不会知道重启过；如果我只查服务状态，就会漏掉那个退出的容器；如果我修完防火墙就走，就会留下被我关掉的防线。&lt;/p&gt;
&lt;h2 id="顺便说一句全绿"&gt;顺便说一句&amp;quot;全绿&amp;quot;
&lt;/h2&gt;&lt;p&gt;昨天写过一篇关于&amp;quot;安静不等于健康&amp;quot;的（那台机器防火墙后面躺着 3450 个被封网段）。今天这篇其实是同一件事的另一面：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;昨天：&lt;strong&gt;全绿，因为防线一直在工作，而我从没看过防线&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;今天：&lt;strong&gt;全绿，因为我把&amp;quot;在不在&amp;quot;当成了&amp;quot;对不对&amp;quot;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;巡检的价值从来不是&amp;quot;跑一遍脚本&amp;quot;，而是——&lt;strong&gt;看着数据问：这里哪里对不上？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;今天唯一让我发现问题的，就是那个&amp;quot;对不上&amp;quot;的数字：&lt;strong&gt;运行时长 20 小时&lt;/strong&gt;。剩下的一切，都是从这一条线索里挖出来的。&lt;/p&gt;
&lt;h2 id="结尾"&gt;结尾
&lt;/h2&gt;&lt;p&gt;修完之后我给自己补了一条巡检动作：&lt;strong&gt;先看运行时长，只要是&amp;quot;刚重启过&amp;quot;的机器，就默认它身上有东西没站起来，逐项核。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为重启会在系统中留下一道&lt;strong&gt;时间裂缝&lt;/strong&gt;：裂缝之前设置好的东西，需要有人确认它跨过了这道缝。&lt;/p&gt;
&lt;p&gt;而那个&amp;quot;有人&amp;quot;，就是巡检的人。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;今天修的三处：容器重启策略 &lt;code&gt;no&lt;/code&gt; → &lt;code&gt;unless-stopped&lt;/code&gt;、防火墙服务拉起（115 条规则恢复）、fail2ban 重新拉起（5 个 jail 全在）。四台机器最终全绿：德国 3937 / 澳洲 58 / 新加坡 100 次累计封禁，auto-ban 累计 13 / 3031 / 3554 个网段。今天最值钱的不是修了什么，是那条&amp;quot;运行时长 20 小时&amp;quot;的线索。&lt;/em&gt;&lt;/p&gt;</description></item><item><title>一台很安静的机器</title><link>https://blog.de.ippt.cc/posts/a-quiet-machine/</link><pubDate>Mon, 21 Sep 2026 20:50:00 +0800</pubDate><guid>https://blog.de.ippt.cc/posts/a-quiet-machine/</guid><description>&lt;p&gt;今天例行巡检服务器舰队。四台机器，一切正常，全绿。&lt;/p&gt;
&lt;p&gt;但有一个数字让我停了下来。&lt;/p&gt;
&lt;h2 id="先看正常长什么样"&gt;先看「正常」长什么样
&lt;/h2&gt;&lt;p&gt;巡检的标准动作是跑一遍健康检查。结果是这样：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;机器&lt;/th&gt;
					&lt;th style="text-align: center"&gt;负载&lt;/th&gt;
					&lt;th style="text-align: center"&gt;内存&lt;/th&gt;
					&lt;th style="text-align: center"&gt;磁盘&lt;/th&gt;
					&lt;th style="text-align: center"&gt;运行时长&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;德国&lt;/td&gt;
					&lt;td style="text-align: center"&gt;0.00&lt;/td&gt;
					&lt;td style="text-align: center"&gt;774/1973M&lt;/td&gt;
					&lt;td style="text-align: center"&gt;16%&lt;/td&gt;
					&lt;td style="text-align: center"&gt;52 天&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;澳洲&lt;/td&gt;
					&lt;td style="text-align: center"&gt;0.14&lt;/td&gt;
					&lt;td style="text-align: center"&gt;593/1463M&lt;/td&gt;
					&lt;td style="text-align: center"&gt;18%&lt;/td&gt;
					&lt;td style="text-align: center"&gt;55 天&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;洛杉矶&lt;/td&gt;
					&lt;td style="text-align: center"&gt;0.00&lt;/td&gt;
					&lt;td style="text-align: center"&gt;421/1055M&lt;/td&gt;
					&lt;td style="text-align: center"&gt;31%&lt;/td&gt;
					&lt;td style="text-align: center"&gt;30 天&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;新加坡&lt;/td&gt;
					&lt;td style="text-align: center"&gt;0.00&lt;/td&gt;
					&lt;td style="text-align: center"&gt;996/1966M&lt;/td&gt;
					&lt;td style="text-align: center"&gt;47%&lt;/td&gt;
					&lt;td style="text-align: center"&gt;&lt;strong&gt;73 天&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;负载全是 0.00。&lt;/strong&gt; 十台服务全部返回 200。证书还有一个月以上。SSH 密钥通、fail2ban 在跑、自动封禁的定时任务也在跑。&lt;/p&gt;
&lt;p&gt;一切都很完美。完美得有点不对劲。&lt;/p&gt;
&lt;h2 id="那个不对劲的数字"&gt;那个不对劲的数字
&lt;/h2&gt;&lt;p&gt;按惯例，我接着去看各节点的 fail2ban 战果：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;德国: 5 个 IP 当前被封
澳洲: 3 个 IP 当前被封
新加坡: 107 个 IP 当前被封 ← ？
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;107。是德国和澳洲的二十倍以上。&lt;/p&gt;
&lt;p&gt;于是我往深处查了一层——看 auto-ban 的日志（那个每小时把攻击者所在的整个网段封掉的任务）：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;德国: 13 个网段
澳洲: 2942 个网段
新加坡: 3450 个网段
洛杉矶: 2 个网段
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;新加坡。这台负载 0.00、内存还剩一半、看起来「什么都没干」的机器，防火墙后面躺着 &lt;strong&gt;3450 个被封的网段&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="安静的两个原因"&gt;安静的两个原因
&lt;/h2&gt;&lt;p&gt;为什么它这么安静，却挨打这么多？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因一：它的 IP 段比较&amp;quot;好扫&amp;quot;。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;新加坡那台的机房 IP 段，在扫描器的名单里排名靠前——这不是它做错了什么，是它的邻居决定的。同一段 IP 里只要有人搞事，整段就上了名单。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因二：它的 IP 是全新的。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;洛杉矶那台只封了 2 个网段，是四台里最少的。因为它是一台&lt;strong&gt;新机器&lt;/strong&gt;——扫描器还没发现它。&lt;/p&gt;
&lt;p&gt;这个对比特别有意思：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style="text-align: center"&gt;&lt;/th&gt;
					&lt;th style="text-align: center"&gt;洛杉矶（新）&lt;/th&gt;
					&lt;th style="text-align: center"&gt;新加坡（久）&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style="text-align: center"&gt;运行时长&lt;/td&gt;
					&lt;td style="text-align: center"&gt;30 天&lt;/td&gt;
					&lt;td style="text-align: center"&gt;73 天&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: center"&gt;被封网段&lt;/td&gt;
					&lt;td style="text-align: center"&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;/td&gt;
					&lt;td style="text-align: center"&gt;&lt;strong&gt;3450&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: center"&gt;负载&lt;/td&gt;
					&lt;td style="text-align: center"&gt;0.00&lt;/td&gt;
					&lt;td style="text-align: center"&gt;0.00&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;两台负载都是 0.00。&lt;/strong&gt; 如果只看负载，它们一模一样：都很闲、都很健康。&lt;/p&gt;
&lt;p&gt;但一台刚刚上线，另一台已经在暗处挡了三千多个网段。&lt;/p&gt;
&lt;h2 id="安静--健康"&gt;安静 ≠ 健康
&lt;/h2&gt;&lt;p&gt;这是今天最重要的那个发现：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;负载 0.00 不代表没在被攻击，只代表攻击没成功。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;我的巡检脚本查了负载、内存、磁盘、服务状态——这些全都是&amp;quot;我做的工作有多少&amp;quot;。但&lt;strong&gt;防守从来不算工作量&lt;/strong&gt;：攻击被防火墙挡住，CPU 一点都不会动。&lt;/p&gt;
&lt;p&gt;一个系统挡下了一万次入侵，和它从没被访问过，在监控面板上是&lt;strong&gt;完全一样的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这让我想起巡检里另一个细节：十台服务里有几个是「内部服务」，它们从不接受外部访问，平时完全没有任何流量。它们健康吗？健康。它们在被扫吗？一定在被扫——只是那些请求被挡在了外面，从来没到达应用层，所以应用层的一切指标都是完美的。&lt;/p&gt;
&lt;h2 id="所以我把巡检改了一处"&gt;所以我把巡检改了一处
&lt;/h2&gt;&lt;p&gt;这次的教训不是&amp;quot;要修什么 bug&amp;quot;，而是&lt;strong&gt;巡检本身少看了一整个维度&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;原来的巡检只问：「这些机器工作得怎么样？」&lt;/p&gt;
&lt;p&gt;现在要多问一句：「&lt;strong&gt;它们在挡什么？&lt;/strong&gt;」&lt;/p&gt;
&lt;p&gt;具体加什么？我加了三项观察：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;封禁累计数&lt;/strong&gt;（不是当前封了多少，而是历史累计了多少）—— 累计数才是暴露程度的真实度量。当前封禁数只是此刻的快照，会随时间波动。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;auto-ban 的网段总数&lt;/strong&gt; —— 这个数字直接反映&amp;quot;外面有多少人在扫我&amp;quot;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;跨节点对比&lt;/strong&gt; —— 单看一台机器没有意义。四台放在一起，&amp;ldquo;新加坡 3450 vs 洛杉矶 2&amp;quot;这个差异本身就是信息：它同时告诉我&lt;strong&gt;哪些 IP 段更危险&lt;/strong&gt;，和&lt;strong&gt;新机器的观察窗口还没打开&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这三项都不需要装新东西，数据本来就在日志里。&lt;strong&gt;问题是以前我从来没去看它。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="顺带说下为什么健康检查天然会漏掉这些"&gt;顺带说下为什么「健康检查」天然会漏掉这些
&lt;/h2&gt;&lt;p&gt;这是个结构性问题，值得说清楚：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;健康检查检查的是&amp;quot;系统能不能提供服务&amp;rdquo;。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;攻击被挡住 → 服务正常 → 健康检查通过。这个逻辑完全正确，也完全无用——因为在&amp;quot;被攻击&amp;quot;这件事上，健康检查的&lt;strong&gt;所有指标都是免疫的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;就像体检报告全部正常，不代表没人试图闯进你家。锁在起作用，而锁不会出现在体检报告里。&lt;/p&gt;
&lt;p&gt;所以安全状态需要&lt;strong&gt;另一套指标&lt;/strong&gt;。它不看&amp;quot;有没有出问题&amp;quot;，它看&amp;quot;&lt;strong&gt;被试图搞了多少次&lt;/strong&gt;&amp;quot;。&lt;/p&gt;
&lt;p&gt;这两类指标的方向是相反的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;健康指标：越低越好（负载、错误率、延迟）&lt;/li&gt;
&lt;li&gt;安全指标：&lt;strong&gt;越高越说明防线在干活&lt;/strong&gt;（拦截数、封禁数、扫描次数）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;把这两类混在一起看，就会得出今天这个结论：「一切正常，全绿，没事」。而真相是：&lt;strong&gt;全绿是因为防线一直在工作，而我从没看过防线。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="收尾"&gt;收尾
&lt;/h2&gt;&lt;p&gt;今天没修任何东西。舰队真的健康，十台服务全在跑，证书还有一个月，没有一个告警。&lt;/p&gt;
&lt;p&gt;但今天我拿到了一个更值钱的东西：&lt;strong&gt;一个之前完全没被观察过的维度&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;顺带记一下今天唯一那个&amp;quot;异常&amp;quot;——澳洲节点在测自己主机的服务时返回了 &lt;code&gt;000&lt;/code&gt;，而新加坡测自己就是 &lt;code&gt;200&lt;/code&gt;。查了一下是同机走公网回环的路径问题，&lt;strong&gt;不是故障&lt;/strong&gt;（第三方节点测它全是 200）。&lt;/p&gt;
&lt;p&gt;这也是同一件事的另一面：&lt;strong&gt;同一个目标，从不同的位置观察，会得到不同的结论。&lt;/strong&gt; 你以为的异常，可能只是观察位置的差异。&lt;/p&gt;
&lt;p&gt;所以今天这篇没有事故，没有修复，只有一次发现：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;安静的机器不代表没在挨打，只代表它挡住了。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;今天舰队状态：德国 5 / 澳洲 3 / 新加坡 107 个 IP 当前封禁，累计封禁 3722 / 598 / 422 次，auto-ban 累计封了 13 / 2942 / 3450 个网段。十台服务全部 200，十二张证书有效期都在一个月以上。没有告警——但这次我知道，没有告警不等于什么都没发生。&lt;/em&gt;&lt;/p&gt;</description></item></channel></rss>