经过几次正常连接后,服务器停止发送 SYN ACK

经过几次正常连接后,服务器停止发送 SYN ACK

我有几千台设备位于 NAT 后面,与两台服务器通信。每台设备都位于本地路由器(例如调制解调器/路由器)后面,通过本地路由器,它们被 NAT 到具有数千台此类设备的专用网络,并且在该专用网络的网关处,来自这数千台设备的 TCP 会话会动态地获得 NAT 过载/PAT,以连接到单个全局 IP 地址上的端口。这意味着,假设设备 1 将与服务器通信,并且连接将来自 global_ip_of_the_router:port_number_1。一旦设备 1 完成通信,并且 NAT 关联被移除,当设备 2 想要与同一台服务器通信时,远程路由器可以为设备 2 分配相同的全局端口,即服务器可以看到新的 TCP 连接来自 global_ip_of_the_router:port_number_1

设备本身启动 TCP 连接,对小文件进行 HTTP 发布,断开 TCP 连接,为下一个文件建立新连接等。对于约 20 个文件,此方法可行,之后在 SYN 上,设备从服务器收到的只是 ACK,没有 SYN。ACK 的 ACK 编号与 SYN 上的序列号完全不同。设备立即发送 RST,后退并在 1 秒后尝试从同一源端口发送 SYN,仍然只是 ACK,因此它会不断后退到 3、6、12、24、48 秒,然后放弃。在设备的 RST 上,它似乎在 ACK 之后使用 SEQ,试图关闭旧连接(从服务器角度来看)

远程主机是 AWS ELB。以下是我们的假设以及我们尝试过的方法:

远程路由器必须将 TCP 会话视为已终止,并使 NAT 超时,并比目标服务器 (ELB) 更快地重用全局端口。这可能导致 ELB 处于 TCP_TIME_WAIT 状态,这就是它使用 ACK 响应 SYN 的原因。由于 ELB 的 TCP TIME WAIT 未知,假设它是 Linux 内核中的标准 60 秒默认值,它将与远程路由器上的 FIN/RST NAT 后超时相匹配。尽管如此,我们在路由器上将其更改为 70 秒以避免任何竞争条件。这并没有让问题消失。我们认为,如果远程路由器更快地杀死 NAT,它会在设备退避时为 SYN 重试分配一个新的 NAT。如果目标服务器上的问题与远程路由器上使用的全局端口号有关,那么看到新的 SYN 来自路由器 IP 上的新全局端口应该会让它摆脱奇怪的状态。现在,虽然我们可以看到它正常工作,但看起来新分配的 NAT 端口在服务器上也遇到了同样的问题,它返回了虚假的 ACK,但 ACK 编号却不同。另一个假设是,只有当 SYN 上的 SEQ 低于使用远程路由器上相同全局端口的最后一个连接的序列号时,才会发生这种情况。即,虚假 ACK 上的 ACK 编号始终高于 SYN 上的 SEQ。(我们将 Wireshark 切换到绝对序列号以查看这一点)。然而,事实证明,我们看到的情况是 SYN SEQ 大于虚假 ACK 上的 ACK 编号。所以那个理论被抛在一边了。我们现在不知道这里可能发生了什么。我们怀疑新的连接获得与旧连接相同的全局端口,但是,如果是这种情况,(a)通过让路由器保持 NAT 更长时间,应该可以阻止它,并且(b)通过让路由器更早地终止 NAT 并为相同的连接尝试分配不同的 NAT,这应该可以避开这个问题。

对于任何有助于理解此行为的帮助都将不胜感激。

Wireshark 跟踪此处:http://www.filedropper.com/traffictrace-anonymizedandpacketswithpayloadremoved

请注意,跟踪已匿名化(IP 和 MAC 已替换),所有带有有效负载的 TCP 数据包都已删除。问题的第一个实例从数据包 129 开始,第二个实例从数据包 382 开始,然后是 463、699、816、1120、1278、1323 等。

查看跟踪中的最后一个实例,这是我们缩短路由器上的 NAT 后 FIN/RST 超时的地方。您可以看到前四次,ACK 的 AKC 编号 = 2899295595。但在第 5 次,ACK 是 3102149417。在第 6 次,它是 4158039292。这是因为在这里,路由器设置为更快地使 NAT 超时,因此这些尝试来自路由器上的另一个全局端口。如果问题与全局端口和使用全局端口的上一个连接有关,那么这应该已经阻止了它。但问题仍然存在,这使我们相信这与源端口无关,而是由 TCP SYN 本身的某些原因造成的。


昨天,我们尝试将 NAT 后 FIN/RST 计时器设置为 300 秒,这些断开的连接就消失了。我猜是我们将端口重用延迟到了 ELB 丢弃了上一个连接的某个时间点。我们想知道 ELB 上设置为 295 秒的空闲超时是否也与 TCP_TIME_WAIT 所用的值相同,或者即使在 FIN 之后也将连接视为有效。虽然如果是这样的话,我们应该会看到更多的连接失败,因为路由器上存在猖獗的端口重用。知道到底发生了什么会很好。

相关内容