在一个线上问题排查过程中,出现了一个新的问题:wget 下载文件在连接建立很短的时间内(1 - 2s)就被 RESET 了。 首先先简要说明一下链路:

客户端经过一个SNAT设备出公网,在服务器上下载一个大文件。端到端的 RTT 大约 90 ms。由于最开始并没有怀疑到 SNAT 设备,并且 server 端无法抓包,我们分别在客户端 和 SNAT 设备到 server 间一台网元设备上抓包。 中间网元设备

SNAT 设备

如上,中间网元设备显示客户端(端口 34567)先发送了 RST 报文,随后服务器(端口 443)响应 RST 报文。但是客户端抓包显示它根本没有发送过 RST 报文。

此时,我们再从 SNAT 设备上抓包,发现就是 SNAT 设备首先给服务器发送了 RST 报文。

这里的 SNAT 设备实际上是一台基于 IPtables 的 Linux 设备。

抓包可以看到,RST 是对一个 TCP Spurious Retransmission 的响应。为什么会发出这个 RST 呢?正好网上有一个相似的场景:Add workaround for spurious retransmits leading to connection resets

总的来说,就是 spurious retransmits 报文在序列号超出 TCP 窗口时,会被 conntrack 认为是 invalid 包,从而不再经过反向 SNAT 规则的处理。由于目的地址没有被转换,报文会按照原来的目的地址送往 INPUT,而本地又没有这个 socket,则响应一个 RST 报文。