出站 ESP 没有回复并不意味着 VPN 已经死了
ESP 每个关联只保护一个方向,不确认任何内容。在断定服务器无响应之前,先把内部对话和入站 SA 对齐来看。
你在 IPsec 主机上抓了包,看到 ESP 数据包发出,却没有看到任何回应,于是断定对端已经坏了。抓包并不支持这个结论。ESP 只保护对话的一个方向,在 IP 层不做任何确认,因此缺少返回的 ESP,既可能意味着应用根本没有话要说,也同样可能意味着隧道已经死了。在责怪任何一端之前,先阅读内部交换和接收侧的状态。
误区:每个受保护的数据包都会换来一个回复
ESP 不是请求-响应协议。它加密并认证策略所选中的内容,接收方验证、解密并交付该内部数据包,而自身不会生成任何数据包。目标忽略的 UDP 查询,或被入站策略丢弃的 ICMP 回显,两个方向都保持沉默,这才是正确结果。把这种沉默当作传输故障,会让你去寻找一个根本不存在的网络问题。
单向抓包实际证明的只是:在该观测点上,发送方的协议栈加密了某个东西。它既不能说明数据是否到达,也不能说明对方是否有意回复。有用的问题不是“为什么没有回复”,而是“内部对话本应产生什么”。
两个 SA,两个 SPI,一次对话
IPsec 安全关联是单向的,因此一次正常的受保护交换会运行一个入站关联和一个出站关联,二者标识符不同、状态独立。按出站数据包的 SPI 去寻找返回流量,是范畴错误,因为任何回复都在对端自己的出站 SA 之下、带着自己的 SPI 传输。应当改用流量选择器和对端地址来配对。
重新协商密钥会让画面在几秒内变得复杂,因为旧状态和替代状态可能重叠。如果症状始于一次密钥更换前后,请把关联标识符和时间戳一起收集,而不只是连接名称。
在任何东西回复之前,接收方必须做什么
| Stage | What to look at | Wrong conclusion if skipped |
|---|---|---|
| Sender encrypts | outbound SA packet counter | "the tunnel is up" |
| Peer receives | inbound SA counter and replay window | "the peer is down" |
| Inner delivery | target host or service logs | "routing is broken" |
| Application replies | the app's own trace | "the reply was dropped" |
| Protected return | the peer's outbound SA | "ESP only works one way" |
每一行都会独立失败,而每种失败有不同的负责人,因此单次抓包无法把它们区分开。入站计数器是数据到达的唯一直接证据,因为未通过认证或重放检查的数据包会被静默丢弃,不产生任何响应。因此,入站计数器没有变化的对端,根本没有向你提供关于其策略的任何信息。
交付是与解密分开的一步。状态可能有效,数据包之后仍可能被入站策略或一条不包含内部目的地的路由丢弃,所以要检查目标主机是否看到了明文,而不是假设计数器干净就说明数据包去了你想去的地方。
原生 ESP 不是 UDP
原生 ESP 是 IP 协议 50,既不是 TCP 也不是 UDP,完全没有端口。因此,允许 IKE 走 UDP 500 的防火墙规则对数据路径毫无说明;围绕端口编写的过滤器可能让隧道完成协商,随后丢弃其中承载的一切。请在你实际观测到的模式下单独测试数据路径。
在 NAT 之后形态会改变:受保护的载荷走在 UDP 内部,通常使用 4500 端口,正如 RFC 3948 所定义。在编写任何规则之前,先记录当前生效的模式,因为路径上的设备可能对原生 ESP 和 UDP 封装的 ESP 区别对待,某些中间设备会放行其中一种而丢弃另一种。
读取属于本次事件的计数器
在 strongSwan 主机上,swanctl --list-sas 会报告每个关联双向的数据包与字节计数器,足以区分“从未到达”和“已到达但无人应答”。在 Linux 上,/proc/net/xfrm_stat 统计聚合性失败,例如缺少状态、缺少策略和协议错误。这些总数自启动起累积,属于单个网络命名空间,因此一个大数字并不构成归因。
在正确的命名空间中,围绕事件窗口取两次读数并比较增量,否则你会把上周的错误安到今天下午的工单上。把命名空间和两个时间戳一并写进工单,让下一位读者能够复现比较,而不是相信一个总数。
要说出阶段,而不是怀疑对象
有用的结论会说明数据包停在哪里:从未收到、收到后被丢弃、已交付但无人应答,或已应答却在返回途中丢失。每一种都指向不同的负责人和不同的下一条命令。“VPN 服务器没有响应”把四种不同的故障压缩成一句话,而抓包从未证明过它。
保持抓包范围狭窄,并且不要把原始内核状态写进工单,因为它可能携带不该离开主机的密钥材料。计数器的增量和时间戳才是值得交给下一位同事的部分。