我有一台TCP服务器在运行Ubuntu 12.04.3(内核3.8.0-31-generic)的机器(“服务器”)上监听。 它从2个不同的客户端机器接收连接。 机器A运行Ubuntu 12.04.4(3.11.0-17-generic),机器B运行Ubuntu 11.10(3.0.0-32-server)。
如果服务器上启用了TCP时间戳(sysctl net.ipv4.tcp_timestamps = 1),则有时来自机器A的SYN数据包将被“忽略”。 在服务器上使用tcpdump(在非混杂模式下),我可以看到SYN到达OK并且有正确的校验和 – 没有响应 – 没有SYN / ACK,也没有RST。 在放弃之前,机器A重传SYN数次。 在机器A上运行的客户机软件(在这种情况下是wget)立即重新尝试一个新的连接并成功,获得即时的SYN / ACK。
机器B在同一台服务器上没有问题,而且stream量看起来很正常 – 它使用与机器A相同的TCP选项(从我从捕获文件中看到的)。 禁用服务器上的TCP时间戳会使所有事情都按照原样工作。
忽略的SYN数据包中的时间戳看起来对我来说是有效的,所以我不确定他们为什么会造成问题,或者它们是根本原因。
我已经把anonyimised pcap在这里https://www.dropbox.com/s/onimdkbyx9lim70/server-machineA.pcap 。 在服务器(10.76.0.74)上显示机器A(10.4.0.76)成功执行HTTP GET(数据包1到10),然后在1秒后尝试再次获取相同的URL(数据包11到17),而是忽略了它的SYN。 数据包18到27是另一个成功的例子。
我怀疑这是一个类似的问题,“ 为什么服务器不会发送一个SYN / ACK数据包,以响应一个SYN数据包 ”,而禁用时间戳是一个解决方法,我想了解是怎么回事。 这只是一个错误?
没有本地防火墙运行。 服务器处理不lessTCP连接(每次约32K),但有大量的空闲内存/ CPU。 在pcap中显示的testing时间,机器A和服务器之间没有其他的TCP连接。 没有迹象表明服务器应用程序的接受队列突然被填满了(除此之外,这应该会影响两个客户端,我会假设)。 由于数据包在服务器上采用的pcap看起来不错,所以似乎并不是一个介入的networking设备正在破坏事物。
我原来在Ubuntu论坛上发布了这个,但事后看来这可能是一个更合适的位置。 希望借来一笔线索。
在我的情况下,以下命令解决了从Linux服务器丢失SYN / ACK答复的问题:
sysctl -w net.ipv4.tcp_tw_recycle=0
我认为这比禁用TCP时间戳更正确,因为TCP时间戳毕竟是有用的(PAWS,窗口缩放等)。
关于tcp_tw_recycle的文档明确指出,不build议启用它,因为许多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.