临时端口冲突

临时端口冲突

有一个客户端应用程序频繁与服务器建立 TCP (HTTP) 连接。连接持续一个请求的持续时间,然后服务器关闭连接,因此服务器上的套接字会在几分钟内处于 TIME_WAIT 状态。随着客户端应用程序反复发出请求,服务器上的 TIME_WAIT 连接数不断增加,并稳定在约 150 个套接字处于 TIME_WAIT 状态。

有时,来自客户端的新连接会选择服务器上处于 TIME_WAIT 状态的最近使用的临时源端口,从而导致连接失败。在 32k 临时端口范围和 150 个套接字处于 TIME_WAIT 状态的情况下,发生这种情况的几率 >10%。确切的情况也在RFC6056 第 2.3 节

我无法控制服务器,因此减少 TIME_WAIT 延迟或更改行为不是一种选择。由于我使用第三方库发出 HTTP 请求,因此更改客户端应用程序以手动选择源端口也很困难。

增加临时端口范围只会稍微降低冲突的概率。有没有办法在客户端(Linux)上更改临时端口选择策略以避免此类冲突?

答案1

套接字TIME-WAIT将很乐意接受来自使用相同 5 元组(协议、源 IP、源端口、目标 IP、目标端口)的设备的新连接,前提是新连接的初始序列号 (ISN) 是更高比上一次连接上看到的最后一个序列号要多。根据RFC 1122

当连接主动关闭时,它必须在 TIME-WAIT 状态下停留 2xMSL(最大分段寿命)。但是,如果满足以下条件,它可以接受来自远程 TCP 的新 SYN,从而直接从 TIME-WAIT 状态重新打开连接:

(1)为新连接分配的初始序列号大于其在前一个连接实例中使用的最大序列号,并且

(2)如果 SYN 被发现是旧的重复,则返回到 TIME-WAIT 状态。

您可以在 Linux 机器上测试这一点,方法是将临时端口范围设置为单个端口echo 32769 32769 > /proc/sys/net/ipv4/ip_local_port_range,然后向设置了Connection: CloseHTTP 标头的网站发出几个连续的请求wget --no-http-keep-alive www.example.com。即使所有连接的 5 元组相同,服务器也会在 TIME-WAIT 中接受新连接,因为每个新连接的 ISN 应该高于套接字上最后看到的序列号。在 Linux 中,新连接的 ISN 应该不断增加 - 它在某种程度上与系统时钟有关。

如果您确信 TIME-WAIT 始终在服务器端结束,并且当您的临时端口被重用时您无法连接,那么您的客户端使用的 ISN 一定不会随着每个新连接而增加(也许是随机选择的或始终使用相同的值?)。如果您可以确保来自客户端的每个新连接使用的 ISN 值都高于上一个,那么您应该能够毫无问题地连接。

相关内容