TCP 重传与 IPsec 重放丢弃:分层读取计数
重传标记、重复 ACK 与 ESP 重放丢弃计数在不同层统计不同事件。请到产生它的那一层读取每个计数器。
三种不同的工具报告三种不同的重复,其中只有一种是你能够处理的网络事件。TCP 重传是发送方再次发送一段范围,重复 ACK 是接收方重复一个确认,而 ESP 重放丢弃是安全联盟拒绝一个已经接受过的序列号。这三者中的任何一个都不蕴涵另外两个。在把它们串成一个故事之前,请到产生它的那一层去读取每个计数器。
三个从不度量同一事件的计数器
TCP 重传注解表示发送方把一段序列范围再次放上了线路。丢包是其中一个原因,而你手里的抓包可能恰好缺少原始报文或能够解释时序的确认。重复 ACK 是接收方在 TCP 恢复规则下重复一个累积确认,它既不是应用层的重复写入,也不是数据的第二份副本。
ESP 在自己的序列空间里工作。每个安全联盟都会给自己发送的报文编号,接收方维护一个已经接受过的序号窗口,因此重复到达的 ESP 报文仅凭这些规则就会被丢弃。所以被重传的 TCP 段会装在一个带新序号的新 ESP 报文里传输,这在两层都是正确行为。同样的字节在一个计数器里看起来是新的,在另一个里看起来是旧的,两层都没有说谎。
分析工具能看到什么、看不到什么
从分析工具的词汇开始,因为过滤器名字描述的是观测,而不是端点的内部状态。用工具所用的同一套名字去计数,能让你对实际测量了什么保持诚实。不完整抓包得到的计数,统计的是幸存下来的东西,而不是线路上发生过的事情。
tshark -r trace.pcap -Y "tcp.analysis.retransmission" | wc -l
tshark -r trace.pcap -Y "tcp.analysis.duplicate_ack" | wc -l
要读那些数字旁边的专家信息,因为校验和与顺序方面的警告会改变它们应得的权重。来自两个传感器的合并轨迹可能把同一个帧显示两次,把两份都算进去就会凭空造出一次从未发生的恢复事件。
ESP 计数器住在内核状态里
ESP 的序号属于安全联盟,而不属于 TCP 流,所以应该到网关上去问。状态列表会报告每个安全联盟的报文与错误计数,这是任何抓包都无法重建的。
ip -s xfrm state
tshark -r trace.pcap -Y "esp" -T fields -e esp.seq | head
RFC 4303 定义了序号以及消耗它的防重放窗口,这就是即使一切正常计数器也会上升的原因。单调的外层序号若没有对应的 TCP 异常,指向的是另一个发送方或重复的路径,而不是重传风暴。加密隧道的外层抓包通常会隐藏内层 TCP 序号,因此它无法证明内层协议栈做了什么。只有在策略允许的地方才在隧道内部抓包,也绝不要为了让无关的警告闭嘴而关闭防重放。
观测点在哪里改变答案
在升级之前,先写清楚抓包是怎么取的:哪个接口、抓包进程有没有报告丢弃、时间戳在不同传感器之间是否可比。一个观测点看不到路径的两端,所以任何关于接收方行为的说法都是推断,而不是测量。在网关上取的轨迹和在主机上取的轨迹会在负载下对顺序产生分歧,而这种分歧通常属于抓包,而不是隧道。把两个视角关联起来,才能把计数变成证据。
使用一条获准的应用流,在同一时刻把端点计数器记录在抓包计数旁边。如果数字不一致,就相信拥有该事件的那一层,并把另一层当作观测伪影,直到有相反的证据。这条规则能在不碰隧道配置的情况下解决大多数这类工单。
按正确顺序读取数字
从提出问题的层开始:TCP 警告要从 TCP 抓包里回答,ESP 丢弃要从网关上的安全联盟计数器回答。然后才去问两个视角描述的是不是同一个报文。需要两层才能成立的结论应当同时点名两层,因为只靠一个 TCP 注解来断言隧道问题只是猜测。
为每一项发现记录层、计数器和观测点,下一位读者就不会把三个事件混成一个想象出来的故障。带着这三个字段去升级,修复通常从第一个字段就能看出来。