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


46

最近,我们发现TCP连接问题主要限于浏览我们网站的mac和Linux用户。

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

我们已经设法跟踪了该问题的技术特征,但无法弄清为什么会发生或如何解决。

基本上,正在发生的事情是客户端的计算机正在发送SYN数据包以建立TCP连接,而Web服务器接收到它,但是没有以SYN / ACK数据包响应。客户端发送了许多SYN数据包后,服务器最终以SYN / ACK数据包进行响应,其余连接一切正常。

而且,当然,这是解决问题的方法:它是间歇性的,不会一直发生(尽管确实会在10%到30%的时间之间发生)

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

Wireshark分析的屏幕截图

Wireshark分析的屏幕截图

更新:

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

最终更新:

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


1
我认为我们需要看到一些tcpdump发生的情况。
coredump

您是否有基于反向DNS的ACL或规则?您可能需要研究的不仅仅是客户端和服务器之间的连接。也许DNS查找超时了?
Zoredache

@coredump:这是wireshark分析的屏幕快照,显示了问题i.imgur.com/Bnzrm.png (无法弄清楚如何仅导出流。...)
codemonkey

@Zoredache:不,我们没有基于反向DNS的ACL或规则。这是一个面向公众的网络服务器,我们允许所有人访问它
codemonkey

只是预感,但是您是否在服务器上进行任何类型的传入连接速率限制?说,用iptables?
星期一

Answers:


15

我们有同样的问题。只需禁用TCP时间戳即可解决此问题。

sysctl -w net.ipv4.tcp_timestamps=0

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

禁用“ TCP窗口比例”选项时要非常小心。此选项对于在Internet上提供最佳性能非常重要。如果往返时间(基本上与ping相同)超过55毫秒,则具有10兆位/秒连接的人的传输将不理想。

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


4
如果有人通过我刚下过的同一个兔子洞来到这里:在关闭TCP时间戳或窗口缩放(这可能会对高流量的链接造成严重的性能后果)之前,请检查tcp_tw_recycle是否是您的问题:stackoverflow .com / questions / 8893888 /…
nephtes

12

就我而言,以下命令解决了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.

1
此处的详细说明:vincent.bernat.im/zh/blog/2014-tcp-time-wait-state-linux 在服务器端,除非您确定不能使用NAT设备,否则请勿启用net.ipv4.tcp_tw_recycle。在混合。
Gnought

1
就我而言,这net.ipv4.tcp_tw_recycle是真正的原因。谢谢。
bluearrow

tcp_tw_recycle已在最近的内核中删除。还有其他解决方案吗?@nephtes表示禁用时间戳会影响性能。
MappaM

由于已删除tcp_tw_recycle,因此不应再次出现此问题,因为仅在使用非默认值tcp_tw_recycle时才发生。
LAV

5

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

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

您能为我们提供539帧内部值吗?SYN / ACK是否总是用于未启用WS的SYN数据包?


@Ansis:这是第539帧详细信息的一些屏幕截图(必须分为两个部分):i.imgur.com/D84GC.pngi.imgur.com/4riq3.png
codemonkey

@codemonkey:您的第8个SYN数据包似乎与前七个SYN数据包不同。仅当tcp.options字段的大小为8个字节(前七个SYN数据包可能具有大小为20个字节的tcp.options)时,服务器才对客户端的SYN做出SYN / ACK响应吗?您可以在客户端禁用TCP窗口缩放以查看问题是否消失吗?似乎是服务器端TCP / IP堆栈出现问题或某处防火墙配置错误...
Hans Solo

@Ansis:是的,自您指出来以来,我一直在研究,所有其他SYN数据包均为24字节。我将尝试在客户端上禁用窗口缩放,并在早上检查结果。
codemonkey

@Ansis:在客户端上关闭Windows缩放功能后,该问题不再发生。谢谢!但是,现在我需要弄清楚如何在服务器端解决此问题(因为我们不能使所有客户端都禁用Windows缩放):)有问题的服务器确实具有net.ipv4.tcp_windows_scaling = 1
codemonkey

@Codemonkey:我同意在所有客户端上禁用WS不是解决方案,但是我们至少已将问题跟踪到WS / Packet Size问题。为了进一步找到原因,我们应该研究防火墙的配置方式。您可以通过WS与其他TCP端口建立TCP连接吗?来自不同的源IP?
汉斯·索罗

4

我们只是遇到了完全相同的问题(确实花了相当长的时间才将其固定到服务器上而不发送syn-ack)。

“解决方案是关闭公众可以访问的服务器上的tcp Windows缩放和tcp时间戳。”


2

继续Ansis所说的,当防火墙不支持TCP Windows Scaling时,我已经看到了类似的问题。这两个主机之间有什么品牌/型号的防火墙?


防火墙是使用iptables的Fedora 13盒。在此计算机上,net.ipv4.tcp_windows_scaling也设置为1
codemonkey

2

缺少的SYN / ACK可能是由于防火墙上的SYNFLOOD保护限制太低所致。这取决于与您的服务器用户创建多少连接。使用spdy将减少连接数量,并且在net.ipv4.tcp_timestamps关闭无用的情况下可能会有所帮助。


1

这是侦听TCP套接字积压已满时的行为。

Ngnix允许在配置中设置backlog参数以进行侦听:http ://wiki.nginx.org/HttpCoreModule#listen

收听80个backlog = num

尝试将num设置为大于默认值的值,例如1024。

我不保证完整的侦听队列实际上是您的问题,但这是检查的第一件事。


谢谢你的提示。我会尝试的。我们已经在OS级别设置了积压,但未在Nginx配置中显式设置。我将更新结果。
codemonkey

它根本没有改变行为。猜猜,这不是问题吗?或唯一的问题...
codemonkey

1
应用程序级待办事项参数控制完成tcp连接的队列大小,即完成3次握手,即收到syn-ack-因此它与OP情况不匹配
ygrek 2015年

1

我刚刚发现Linux TCP客户端经过3次尝试后会更改其SYN数据包,并删除了“窗口缩放”选项。我猜内核开发人员认为这是Internet连接失败的常见原因

它解释了为什么这些客户端在11秒后设法连接(无窗口TCP SYN在我使用默认设置的简短测试中在9秒后发生)


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.