TCP保持活动在TCP零窗口后涉及并错误地关闭连接

时间:2015-11-09 22:31:26

标签: tcp wireshark keep-alive

我们看到这种模式在通过TCP连接传输数据的两个RHEL 6盒之间发生了很多。客户端发出TCP窗口满,0.2秒后客户端发送TCP Keep-Alives,服务器响应的内容看起来像正确形状的响应。然而,客户端对此不满意,并继续发送TCP Keep-Alives,直到最近9秒后它终于关闭与RST的连接。

尽管RHEL盒具有默认的TCP Keep-Alive配置:

net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75

...声明这应该只发生在2小时的沉默之后。我是否错误地阅读了我的PCAP(可根据要求提供相关数据包)?

以下是该模式的Wireshark截图,中间有我自己的数据包备注。

Wireshark screenshot

4 个答案:

答案 0 :(得分:2)

实际上,这些“保持活动”数据包不用于TCP保持活动!它们用于检测窗口大小更新。

Wireshark将它们视为保持活动数据包,只是因为这些数据包看起来像保持活动数据包。

  

TCP保持活动数据包只是一个ACK,其序列号设置为小于当前连接的序列号。

(我们假设ip 10.120.67.113引用主机A,10.120.67.132引用主机B。)在编号249511的数据包中,A序列号24507484。在下一个数据包(编号249512)中,B发送序列号24507483( 24507484-1)。

enter image description here

为什么有这么多“保持活动”数据包,它们是用来做什么的?

A向B发送数据,B答复零窗口大小以告诉A他暂时不再接收数据。为了确保A知道B什么时候可以再次接收数据,A用persistence timer一次向B发送“保持活动”数据包,B用窗口大小信息回复A(在我们的例子中,B的窗口大小始终为零)。

在计算持久性计时器时,将使用常规的TCP指数补偿。因此,我们可以看到A在0.2秒后发送了它的第一个“保持活动”数据包,在0.4秒后发送了它的第二个数据包,第三个在0.8秒后发送了,第四个在1.6秒后发送了。

此现象与 TCP流量控制有关。

答案 1 :(得分:0)

源自客户端的数据包中的源IP地址和目标IP地址与响应数据包中的目标和源IP地址不匹配,这表明在执行NAT的框之间存在某些设备。了解数据包的捕获位置也很重要。客户端本身的数据包捕获可能有助于理解这个问题。

请注意,如果客户端在两小时或更长时间内未收到数据包,则可以生成TCP keepalive。根据RFC 1122,如果客户端没有收到来自对等方的keepalive响应,则会重试keepalive。在连续重试失败后,它最终会断开连接。

NAT设备通常实现连接缓存以维持正在进行的连接的状态。如果连接的大小达到限制,NAT设备将丢弃旧连接以便为新连接提供服务。这也可能导致这种情况。

给定的数据包捕获表明数据包很可能没有到达客户端,因此在客户端计算机上捕获数据包会很有帮助。

答案 2 :(得分:0)

我的描述略有不同: 发送者发送的数据多于接收者可以处理的数据并获得zerowindow响应 发送者发送窗口探测器(不是keepalive,很快就会这样)并且应用程序在10秒后放弃而没有进展并关闭连接,重置表明TCP sendbuffer中有待处理的数据。 如果应用程序使用大块大小写入套接字,则可能在tcpdump中看到的时间超过10秒没有进展。

如果这是直接连接(没有代理等),最可能的原因是接收停止接收(或者比发送器和数据传输慢)

答案 3 :(得分:0)

在我看来,数据包号码249522激活了10.120.67.113上的应用程序以中止连接。所有窗口探测器从.132(没有有效载荷)获得零窗口响应,然后.132发送(未经请求的)具有63字节的数据包249522(并且仍然显示0窗口)。 PSH标志表明这个63字节是应用程序在.132上写的整个数据。然后.113在相同的毫秒内响应RST。我想不出TCP堆栈在接收数据后立即发送RST的任何原因(序列号是正确的)。在我看来,几乎可以肯定.113上的应用程序决定根据.132发送的63字节消息放弃。