为什么服务器不会发送 SYN/ACK 数据包来响应 SYN 数据包

为什么服务器不会发送 SYN/ACK 数据包来响应 SYN 数据包

最近,我们意识到存在一个 TCP 连接问题,该问题主要限于浏览我们网站的 Mac 和 Linux 用户。

从用户的角度来看,这表现为我们与网站的连接时间非常长(>11 秒)。

我们设法追踪了该问题的技术特征,但无法弄清楚其发生的原因或如何解决它。

基本上,发生的情况是客户端的机器正在发送 SYN 数据包以建立 TCP 连接,并且 Web 服务器接收到该数据包,但没有使用 SYN/ACK 数据包进行响应。在客户端发送了许多 SYN 数据包之后,服务器最终使用 SYN/ACK 数据包进行响应,并且连接的其余部分一切正常。

当然,问题的关键在于:它是间歇性的,并不是一直发生的(尽管它确实会在 10-30% 的时间内发生)

我们使用 Fedora 12 Linux 作为操作系统,并使用 Nginx 作为 Web 服务器。

wireshark分析截图

wireshark分析截图

更新:

关闭客户端上的窗口缩放功能可阻止该问题的发生。现在我只需要一个服务器端解决方案(我们不能让所有客户端都这样做):)

最后更新:

解决方案是关闭两者TCP 窗口缩放 TCP 时间戳在我们可供公众访问的服务器上。

答案1

我们也遇到了同样的问题。只需禁用 TCP 时间戳即可解决问题。

sysctl -w net.ipv4.tcp_timestamps=0

要使此更改永久生效,请在 中进行输入/etc/sysctl.conf

禁用 TCP 窗口缩放选项时要非常小心。这选择很重要提供最佳的互联网性能。如果往返时间(基本与ping相同)超过55毫秒。

当同一 NAT 后面有多台设备时,我们确实注意到了这个问题。我怀疑服务器可能会混淆同时看到来自 Android 设备和 OSX 计算机的时间戳,因为它们在时间戳字段中输入了完全不同的值。

答案2

就我而言,以下命令已修复 Linux 服务器缺少 SYN/ACK 回复的问题:

sysctl -w net.ipv4.tcp_tw_recycle=0

我认为这比禁用 TCP 时间戳更合适,因为 TCP 时间戳可用于高性能(PAWS、窗口缩放等)。

文档中tcp_tw_recycle明确指出不建议启用它,因为许多 NAT 路由器保留时间戳,这可能会导致 PAWS(针对包装序列的保护)激活,因为来自同一源 IP 地址的时间戳可能会变得不一致。

   tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)
          Enable fast recycling of TIME_WAIT sockets.  Enabling this
          option is not recommended for devices communicating with the
          general Internet or using NAT (Network Address Translation).
          Since some NAT gateways pass through IP timestamp values, one
          IP can appear to have non-increasing timestamps.  See RFC 1323
          (PAWS), RFC 6191.

答案3

只是想知道,为什么对于 SYN 数据包(帧#539;已被接受的数据包),“信息”列中缺少 WS 和 TSV 字段?

WS 是TCP 窗口缩放TSV 是时间戳值。它们都在 tcp.options 字段下找到,如果它们存在,Wireshark 仍应显示它们。也许客户端 TCP/IP 堆栈在第 8 次尝试时重新发送了不同的 SYN 数据包,这就是它突然被确认的原因?

您能为我们提供帧 539 的内部值吗?SYN/ACK 是否始终针对未启用 WS 的 SYN 数据包发送?

答案4

SYN/ACK 丢失可能是由于防火墙上的 SYNFLOOD 保护限制过低造成的。这取决于用户与服务器建立的连接数。使用 spdy 可以减少连接数,并且在关闭 spdynet.ipv4.tcp_timestamps不起作用的情况下可能会有所帮助。

相关内容