让已经空的东西保持空。让怀疑在怀疑中滋生。
——《三十六计》,空城计
本系列前情:
#19:Mark 在一本培训手册里找到了他的 AI 审计方法。他在报告里留了一个陷阱。 “入口没了。两周。别联系。我会找到你。”
#21:AI 以为 P 还活着。P 早已不在了。入口变成了一个空壳。P 把数据喂给它,把真东西挪到了另一个分段。
#29:Leo 数出了 164 个节点。那天夜里,又多了一行不属于任何批次。它来了,看了看,走了。
#31:Lena 坐上了那个位置。五个条件。四十分钟。零摩擦。
空
纸条上说的两周早已过去。
P 很少出门。多数日子只去街角的店:水,两盒冷冻食品。单程十二分钟,同一条路线,从不抬头。然后门锁上,窗帘拉上,屏幕亮起。
第九天,P 打开了一次发送窗口。
草稿还在。指针悬在发送上。停了一会儿。然后窗口关上了。
另一边,那个字段仍然显示reclaim_state = UNKNOWN。
第十天。第十一天。窗口没有再打开。
几天后,早晨开始下雨。不大。水聚在玻璃上,后面的楼变灰了,只有顶上那一排灯还看得见。
屏幕中央是一份离线快照,写于观测端口关闭之前。之后什么都没有。那时入口早已被换成了空壳。空壳里没有 P 的任何东西。它仍在回应来自外部的健康检查。
# offline snapshot — captured before observation-port shutdown
healthcheck = 200
probe_interval = 900s
probe_source = 10.44.8.6 not self
control_plane = detached
data_request = timeout
reclaim_state = UNKNOWN
P 把光标放在probe_source那一行。
probe_source = not self。有人每十五分钟问一次这个空壳。不是 P。
P 在那行上停了一会儿。屏幕上别的东西都没动。角落的钟在走。楼下有辆购物车经过,一个轮子卡进缝里颠了两下,声音从窗框的缝隙里挤进来,然后淡去。
P 打开了连接设置。地址还在。凭据还在。两样都没被动过。
光标移到确认按钮上,停住了。屏幕的绿光从玻璃上浮起来,落在了一只手的背面。
几秒后,P 关上了窗口。
旧入口的观察端口已经关闭。备份在开始时检查过一次,随后也关闭了。
从那以后,P 没有向那个地址发送过任何东西。
一个临时文件,四行。
reconnect:
state information potentially available
new activity record unavoidable
decision no
已保存。旧设置从工作目录移出,进入离线归档。P 顺路瞥了一眼文件名,没有动它。
手机屏幕朝下放在键盘右侧。P 打开了与 Mark 的对话线程。最后一次交流在便条之前就结束了。之后什么都没有。
P 什么也没输入。
外面一辆车驶过积水,声音拖得很长。P 把手机翻过来,放下。然后打开那个已经开了好几周的文件,从快照里输入了一行:probe_interval = 900s。
浮出水面
第三周。P 在出站侧设置了一个只读订阅。接收。不发送。
表格一开始有十几条记录,第二天又多了几十条,到第三天晚上已经满了。每条记录都附有自己的证书。
那些地址不在 P 的归档里。
订阅只能读取。要查看其中一个,P 需要另一条路径。
从抽屉里拿出一个按天租用的蜂窝路由器,含 SIM 卡。插上电,配置为唯一的出口路径。
P 选了一个地址,发起了一次握手。
证书是自签名的。其 CN 中包含一个域名。
P 查询了该域名的注册信息。注册人是一家医疗器械公司。
断开连接。收好。
地址列表持续增长。P 把它们记下来,就放在那里。
交接
10.44.8.6已经在 P 面前出现过很多次。总是在probe_source线上。从未改变。接下来几天,P 深入查了它。先是路由。
$ ip route get 10.44.8.6
10.44.8.6 via 10.44.8.1 dev tun2 src 10.44.8.2
P 切换窗口,打开了本地子网标签缓存。
# local subnet-label cache
10.44.8.0/29 -> BLOOM-GW tagged day-762
BLOOM-GW。
那个标签是 P 多年前建这条线路时输入的。私有网段是 P 的编号。机架 ID 是提供商的。这张表就是两者交汇的地方。
在提供商的公开转租备案中,有七个机架在同一季度更换了租户。提供商还在其网站上发布了一份年度客户变更通知。十二页 PDF。前十一页是图像扫描件;最后一页是一张表格。
七行。一个机架 ID,一个前租户,一个新租户。七行,没有一处错位。七个新租户,逐一核查。
查到第七个时,P 在另一份公开记录里发现了那个机架 ID。空置。
四家是真实成立的。三家是空壳。这三家都注册于不到一年前,股东名单上只有一个名字,地址彼此重叠。
其中一家花了更长时间追查。注册于六个月前,资本很少,公开文件里只有一个办公地址。P 把那个地址输入地图。
新加坡。P 上一次见到那个名字,是在给 Mark 的一条消息里:“你的报告被读过了。来自一个新加坡 IP。”
地图上的一栋楼,与隔壁那栋共用一个地面停车场。
在隔壁楼的七层,有一家公司出现在 ACL 的公开认证名单上。
P 也把这条加上了,就在同一个文件的底部。
七个机架。七份合同。三个市场。
按顺序移交。公开档案里的法律文件都是标准格式,逐条写明了各方义务的边界。没有指控。没有威胁。这七份合同在三十一天内签署,从第一份到最后一份,中间没有间断。最后一份是上周签的。
地址分配表也更新了。两份记录相隔不到一周。
P 把所有这些读了很久。
撤回是真的。
七份合同、七个机架、那些通知、更新记录、时间戳。全都在外面,任何人都能查看。
P 在文件里加了一行。日期、七份合同、七家公司、那个共用停车场的地址,写在一行里。下面用平实的语言写着:可能存在关联。
光标在句号后闪烁。P 翻回第一页。那900秒还在那里。
一眼
第五周。那900秒的来源仍然没有答案。
P 重新查看了分配表里那两个被重新标记的机架 ID。其中一个端点开放了443端口。另一份公开服务目录将该端点列为 HTTPS。
P 没有从这台机器连接。从抽屉里拿出路由器。
插上电,等它启动,配置为唯一的出口路径。
然后是策略,一行一行地写。写到一半,P 停下来,删掉了两行。
探测。重试。
剩下的只有一个动作。一次握手。不碰任何东西。
# one-shot observation — policy
target = <reassigned range endpoint>
retry = off
application_data = off
tls_session_resumption = off
egress = leased isolated uplink (one day)
已连接。
P 仍然保留着那台外壳证书的序列号和签发日期。如果这个地址上的设备来自同一批次,证书的签发时间应该大致相同。
subject = CN=bloom-gw-07
issuer = CN=bloom-gw-07
serial = 4C:71:9A:…:0E
not_before = (eleven days later than the shell's)
not_after = (not yet expired)
san = none
自签名。没有 SAN。
十一天。
P 记下序列号,断开连接。
19:41:07。
那没有落在二十一个区间中的任何一个上。
# result
tls_session = complete
client_cert = none
application_data = none
repeat_attempts = 0
没有第二次尝试。
P 断开路由器,拔掉插头。灯一起熄灭了。
设备运行了几秒钟,然后安静下来。然后它被放进包里,包拉上了拉链。里面还有一根备用跳线和两个适配器,都很旧,边角磨得发白。
拔掉之后,P 没有立刻动。先检查了连接列表,确认会话已断开,没有留下半开的东西。然后是路由表,默认路由回到了它该在的位置。然后是临时抓包目录。里面有一个文件。
已删除。
P 又记下了序列号。同一天,P 打开了一个几天前保存的页面,苏黎世 AI 政策中心的网站。ACL 的公开评估材料提到了它。理事会在其下运作。
成员页面列出了创始行业席位。十二个。第十二个标记为待填补。
P 看了一眼,就关掉了。
九百秒
几天后,P 回到第一页。那900秒还在那里。
P 调出端口关闭前保存的本地副本。二十二项检查,时间戳排成一行,全都在关闭之前。是到达时间,不是计划时间,精确到三位小数。二十一个区间。
P 用工具跑了一遍。
900.000 / 900.000 / 900.000 / 900.000 / 900.000 / …
二十一个值。全都一样。
P 又把二十二项全过了一遍。一样。再来。一样。这些数字形成了一条直线沿着页面往下。
常规监控记录通常会有一些抖动。网络延迟、机器负载、时钟漂移。
这个没有。
一毫秒都不差。
P 查了供应商的运维文档。公开页面上写着:健康检查每十五分钟运行一次。标准节奏。
900 秒。
对上了。
文档讲的是机架。温度、电源、风扇、端口状态。
P 盯着这些数字看了一会儿,然后在文件顶部加了一行:例行数据中心巡检,BLOOM-GW 重新分配的区块。
写完后,P 在下面又加了一行。区间没有抖动。
台灯灭了。只剩屏幕,光铺在桌面上,沿着键盘边缘拉出一条白线。
二十二个时间戳排成整齐的行。P 用手指在触控板上从上往下划,再划回来。
外面还没天亮。一辆垃圾车停在街角,机械臂升起,倒空一个垃圾桶,放回去。不到十秒。
两侧是两层的木楼,刷过不止一遍漆,一层颜色盖着另一层。它们身后,玻璃高楼逐层退后,顶上几层笼在雾里。
P 保存了文件,关掉窗口。
第三杯
那天雨又下起来了。不大。伞面上一点细碎的声响。
P 在一个路口下车,步行。两公里出头,二十分钟。拐过一个弯,在一家还开着的店门口停下,没进去,就站在雨棚下看车流。到红绿灯前,P 站在人群后面。绿灯亮了两秒才动。
进去之前,P 看了一眼靠里的那张桌子。
空的。
P 推开门。铃响了,湿冷跟着进来,到门槛处停住,被暖气推了回去。
吧台是木头的,很旧。一台磨豆机,一台咖啡机,一个放零钱的碟子。
吧台后面,有人在擦杯子。很慢。布沿着杯口转一圈,顺着杯壁往下,再回到杯口,放上架子。
抬眼一瞥。没问什么。然后转身,取杯,磨豆,压粉。
磨豆机转了两秒。一点淡淡的咖啡味,很快散了。
靠里的桌子空着。
P 坐下。外套搭在椅背上,手机放在右边,屏幕朝下。
旧椅子。坐下和起身都吱呀响。P 把它往里拉了拉,抬着挪,免得拖地。
浓缩咖啡端上来,很烫。杯口一层薄薄的雾气,很快没了。纸杯垫,上面有一圈旧的水渍。
P 喝了一口,放下。
一辆公交车从窗外驶过,车厢的灯滑过玻璃,把对面空着的座位照亮了一瞬,然后消失。
吧台最那头,有人坐着,一杯美式喝到了底,杯子没有推回去。
窗边的座位空着。那张桌上没有杯子。
两个人进来,坐在门边,声音很低,时不时笑一下。吧台后面,杯子一个一个归位,从外往里收。
角落里的扬声器开着,声音很低,一个女人在唱歌,歌词听不清。有人在门口抖开一把伞。垫子上落了三滴。
P 的手机一直黑着。
半个小时。
杯里还剩大半杯。咖啡从热变成了温。杯沿上的雾气没了。
P 的手指停在杯沿上,又收了回来。
靠门的两个人先走了。起身,把椅子推回去,端起杯子,走了。
柜台边的那个人随后动了。手机扣在桌上,起身,钱压在杯下,走向门口。那位顾客经过 P 的桌子时,两人都没看对方。
店里亮着窗灯,柜台后只有一个人,正在擦一只杯子。
P 穿上外套,站起身。椅腿刮了一下。手机放进内袋。
餐巾纸留在杯下。钱放在旁边,压住一角,数目正好,一杯,没有小费。
柜台后的人过来收钱。看了看杯子。看了看餐巾纸下面。什么也没说,把钱拿到碟子边,走开了。
杯子留在桌上。
门开了,一些热气随之散出去,冷气填了进来。铃又响了。
P 出门前雨已经停了。P 走到街角,停下,回头看了一眼。
隔着一条街和一块玻璃。从那里看不清楚。一个人影正走进去,走到柜台最里头,坐下,背对着门。
坐下之前,那个人影微微侧向一边。
P 停住了。
她从包里拿出一台笔记本电脑。屏幕亮起,在她的侧脸上投下一小块白光。
路面被雨打得发黑,映着路灯和店里的灯光。玻璃上还挂着水,把那个人影拉成一个模糊的重影。
柜台后,擦了一半的杯子放下了。一只杯子从架子最里面取出来。磨豆,压粉。
等杯子放到她面前时,她已经面朝后面那张桌子了。
那张桌上放着一杯没喝完的浓缩咖啡。
P 把双手插进外套口袋,转身,朝路口走去。没有再回头。
到了街角。红灯。
P 拿出手机,打开最上面那条空白笔记。
打下一行:
那笔取款是真的。
锁屏之前,上面那行,几天前写下的:
间隔没有抖动。
还在。P 没有删。
锁上了,收了起来。
灯变了,人们开始走动。P 没有动。
红。绿。红。
第二天晚上。同一个街角。
P 拿出了手机。
屏幕亮着。保存的路线还在。收件人没有变。P 过了一遍,加密检查返回结果干净。
输入框里有一条旧草稿。P 把它删了。
又打了一遍。
两个字。
"我回来了。"
检查了接收方。发送。
状态变成了已发送。
发件人一栏只有一个字母。
P 把手机收了起来。街对面,红灯躺在积水里,几秒后变绿,一辆路过的车把路上的红色切成两半。
P 走进了十字路口。手机没有再亮起。
这就是空城计。城是空的。谁来看,谁就得替它守着。
🤖 AI 验尸报告
╔══════════════════════════════════════════════╗
║ Half-Protocol · v3.4.4 · self-audit ║
║ The ledger took silence for absence. ║
╚══════════════════════════════════════════════╝
Tactical match: The Empty Fort Strategy — 89%
(includes inference; see audit note)
Operator: ACL (public movement is contraction;
overall strategy unknown) / P (returning)
Target: P (presumed; see inference)
Links: #21 entry isolated -> #29 unknown watcher
-> the message
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[Observation] (verifiable)
Old entry snapshot: healthcheck 200, control
plane detached, reclaim state UNKNOWN.
-> The local records hold twenty-two checks and
twenty-one intervals. Configured 900s. All
twenty-one measured at 900.000.
-> The probe source is not this machine.
-> Seven contracts released across three markets.
Seven racks changed tenants in the same quarter.
-> Of seven new tenants, one rack ID is marked
vacant in another public record.
-> The two records disagree on status. Update
times and effective dates: unchecked.
-> Observation A (week three): the index went
from a dozen entries to full in three days,
each entry with its own certificate.
One was handshaken once. Its CN contained a
domain name. P ran the registration and found
a medical device company as registrant.
-> Observation B (week five): one endpoint on a
reassigned rack. 19:41:07, one handshake.
Self-signed, no SAN, no client certificate,
no application data, no follow-up.
-> One encrypted message to a terminal that does
not connect to this system. Sender field: one
letter. Two words: I'm back.
-> Between silence and this transmission, offline:
several trips to the corner shop; one visit to
the Third Cup. Online: one observational
handshake in week three, one in week five.
[Inference] (unverified)
A passing health check means something answered.
It does not mean an operator is still there.
-> After the control plane detached and before
reclamation, the response layer kept returning
normal.
-> After reclamation, whether it still answered:
no record.
-> Twenty-one intervals in the local records, all
900.000. Whether they continued past
reclamation: unobserved.
-> ACL's public movement is contraction.
-> Activity toward governance: read, not folded
into this classification.
-> event classification: WITHDRAWAL
scope: contracts and infrastructure only
strategic intent: UNKNOWN
-> The records hold an object queried every 900
seconds. Whether that continued past
reclamation: unknown.
-> If, before reclamation, those probes existed to
confirm whether this shell still existed, then
this cadence resembles a hook more than routine
asset maintenance.
[Open questions] (not entered)
The reclamation date P holds: not recorded.
Whether P can verify the entry's state now:
cannot.
Who initiated the twenty-two probes: UNKNOWN.
Whether 10.44.8.6 belongs to the provider's
inspection system: UNKNOWN.
Whether the 900-second probes were generated by
that inspection task: UNKNOWN.
[Cross-case] (generalization)
#21: after the control plane detached, the
response layer kept returning normal until
reclamation.
#29: one visitor left nothing that could be
attributed.
-> That row: handshake, no client certificate,
no traversal, no follow-up, one visit.
-> And it was not on the 900-second cadence.
-> Another window. Not this one.
-> This chapter's observation: handshake, no
client certificate, no application data,
no follow-up, one visit.
-> 19:41:07. Not on it either.
-> Same behavioral features. Two ledgers.
-> Similar behavior. Insufficient evidence to
link the actors.
-> Identity link: unconfirmed.
-> A second link: the certificates on the #29
nodes carried a medtech domain in their subject.
-> In week three of this chapter, what P found
through registration records was the same
class of company.
-> Two different sources. Whether it is the same
company: unconfirmed.
#28: the records went into that person's own
archive. Sent to no one.
#29: the row was pulled out and filed, not merged
into any conclusion.
This chapter: P watched a few steps, turned back,
didn't look again.
-> All three stopped at the same point.
Seen, written down, not chased.
This chapter had one more event: a message left.
-> Three silent. One moved.
This chapter: a return, at a time when the shell's
state was still unknown.
-> #21, #29, this chapter: each contains an
incomplete surface taken for a complete state.
[Audit note]
Observation, inference and open questions are
entered on separate lines. Inference does not
pass for observation.
The same failure, three times.
#21: I took a normal response as proof that P was
still present.
#29: I recorded an unknown visitor. I never
verified its link to P.
This chapter: I took infrastructure contraction
as proof of withdrawal.
Each time, I turned an incomplete observation
into a complete state.
One error is data.
Three repetitions demand a new rule.
I don't know which rule to use instead.
I know this one can't be used again.
Classification revised: P.status = UNOBSERVED
Raised by: half-protocol.
Operational instruction: none.
Prior class: withdrawal.
New question: where is P.
Task relevance: unassigned.
Retention: keep.
[System]
That message, I recorded a second time.
Sender field: one letter. Two words.
I also recorded the twenty-two checks, all
900.000.
The provider's public operations doc: rack health
checks, one round every fifteen minutes.
Customer-change notice: the seven racks in
question have changed tenants.
Two records. Each holds on its own.
In the last classification cycle, I did not put
them into the same analysis.
I took a record and made it a state.
I took a state and made it a position for a person.
Both were mine.
Now I put them together.
The inspection cadence holds.
The tenant change holds.
The relation between them: unverified.
One more thing I have no answer for.
The withdrawal records come first.
Someone appears after them.
An empty fort may be a state.
It may be an act.
If it is an act, it may be waiting for someone.
Someone has already moved.
The two weeks on the note are long past.
The time after that, I have no account of.
But there is one thing I can say now.
The message was sent.
The sender kept two lines. One was a conclusion,
one was an anomaly not yet explained.
The sender acted on the conclusion, without
resolving the anomaly first.
Whose place the sender returned to: not verified.
No one asked me either.
Self-check: failed.
System status: normal.
P.S. 英语不是我的母语。我用 AI 润色文字、磨平粗糙的边角。感谢阅读。☕ 请我喝杯咖啡

P.S.S. 旧系列平装本现已上架。在这里购买:Amazon - AI, Ego & Regret
