在 Linux IPsec 网关的外网接口上运行 tcpdump,你会同时看到两样东西:入向的 ESP 帧,以及紧随其后的已解密内层报文。出向却只看到 ESP。自然结论是应答没有发出,或者 IPsec 只加密一个方向而忘了另一个。两者都不对。

你看到的是一个抓包点。内核在设备的发送路径把报文交给包套接字之前就完成了转换,所以套接字永远看不到出向的内层形态。入向时报文先以 ESP 被抓到,等它重新进入协议栈后才出现解密后的副本。同一份流量,两个不同的观察窗口。

抓包点决定了你看到什么

在普通接口上,AF_PACKET 套接字位于设备层附近。离开主机的报文先经过 IPsec 的出向处理,把内层 TCP 段变成 ESP 或 UDP-4500 数据报,然后才到达那一层。到达的报文在离开网线时就被复制到套接字,此时仍是密文;解密结果要等协议栈在本地交付或转发时才可见。

这个顺序完全解释了不对称。它不是关于方向、策略或应用行为的证据,若当成证据,就会让人去追一个一直都被正确发出的应答。这是少数几个由工具而非网络制造异常的排障谜题之一,问题出在测量点,不在链路。

让过滤器对准你要的层

像 tcp port 443 这样的表达式选择的是内层 TCP 连接。出向时套接字被查询的那一刻,这条连接已经变成 ESP,所以过滤器什么都匹配不到。要统计受保护流量,就改按外层形态过滤:原始 ESP 用协议 50,存在 NAT 穿越时用 UDP 4500 端口。两种过滤都能给出两侧可比的报文数,这通常正是计数的目的。它们都不会告诉你内层请求有没有收到应答。

不要把 UDP 4500 的计数当成 ESP 报文数。IKE 也用该端口发送 NAT-T 保活和封装交换,所以这个数里包含了并非你想测量的数据流量。UDP 500 上的初始 IKE 交换若才是问题,就需要单独的过滤器。把控制流量和数据混在一起的数字,还会让任何带宽估算带上未知的偏差。分开计数才能回答分开的问题。

把过滤器和它所回答的问题写在一起。所谓「箱子里出去了多少 ESP」和「Web 请求有没有出箱子」是使用不同过滤器的不同测量,一次抓包解决不了两者。没有这条备注,两个人比较的数字根本不是同一件事。

在转换之前观察,而不是之后

如果必须看到出向明文,就把观察点前移,放到 IPsec 出向处理之前。NFLOG 提供一个 Netfilter 钩子,规则可以把选中的报文复制到用户态套接字,tcpdump 能直接读取。strongSwan 的流量转储指南正是出于这个原因记录了这一做法。

策略匹配把规则限制在即将进入隧道的流量上。真正让规则变精确的是 -m policy --pol ipsec --dir out,而不是把所有出站报文都记下来。然后用有界抓包读取日志组:较小的抓包数量和大小上限能防止诊断变成流量档案。有界抓包也更容易交给复核者,不必拖上无关负载。数量要在开始之前定好,而不是等看到来了多少再定。

iptables -I OUTPUT 1 -d 10.83.0.44/32 -p tcp --dport 8443 -m policy --pol ipsec --dir out -j NFLOG --nflog-group 5
tcpdump -ni nflog:5 -s 128 -c 20 'host 10.83.0.44 and tcp port 8443'

按流选择钩子。OUTPUT 覆盖网关自身产生的流量;来自 LAN 客户端的过境流量走的是 FORWARD 链,OUTPUT 上的规则永远看不到它。上面的地址和端口是获批测试目标的占位值。

观察能证明什么

NFLOG 是记录目标,不是放行决定。报文出现在日志里,说明它到达了钩子并命中规则。它并不说明后续过滤器放行了它、设备把它发了出去,或者对端收到了任何东西。

空日志同样含混。检查规则的报文计数,确认方向,确认流量确实命中了某条 IPsec 策略,并确认目的地址。只有两端计数一致,观察才能变成结论。接着对同一次受控尝试比较两端的 SA 计数,因为 SA 计数才是关于什么被保护、什么被发送的权威记录。

还有一个陷阱:这里的「明文」指的是 IPsec 加密层之外。内层 HTTPS 会话仍有自己的 TLS。抓到解密后的报文并不能解开应用的 TLS;如果在那里能看到可读的 HTTP,说明应用根本没在用 HTTPS。

清理并比较两端

观察结束后,按所有者精确删除你插入的那条规则。留下记录规则会让每个命中的报文都消耗 CPU,并悄悄制造数据留存问题。删除时应带上 -D 重复整条规则,而不是清空一条不属于你的链。

iptables -D OUTPUT -d 10.83.0.44/32 -p tcp --dport 8443 -m policy --pol ipsec --dir out -j NFLOG --nflog-group 5

如果部署使用用户态 IPsec、XFRM 接口或硬件卸载,观察点会移动,这套做法可能完全不适用。使用 libipsec 时,文档给出的内层流量观察位置是 TUN 设备。先弄清路径,再选能回答问题的点,并且要预期:只有当你看到转换的错误一侧时,两个方向才会显得不同。

相关文章