TCP接收数据包,但忽略它们。

5
我有一个非常奇怪的网络问题。实际的网络配置相当复杂,因为我正在使用Openstack和Docker来构建虚拟网络。然而,这个问题不在那里,因为我正在捕获我的主机接口上的数据包,并且我以正确的方式看到所有数据包...但是由于某种我不知道的原因,似乎TCP忽略了它们,尽管它们已经被接收:它不会发送ACK,并且不会将数据发送到应用程序。
在我的测试中,我从主机(192.168.4.100)向服务器jetty(IP 192.168.4.3)发送了HTTP GET请求以获取html页面。
在使用Wireshark捕获192.168.4.100时,我看到的是:
192.168.4.100 -> SYN -> 192.168.4.3
192.168.4.3 -> SYN, ACK -> 192.168.4.100
192.168.4.100 -> ACK -> 192.168.4.3

192.168.4.100 -> GET / HTTP/1.1 -> 192.168.4.3
192.168.4.3 -> ACK -> 192.168.4.100
192.168.4.3 -> Fragment 1 of HTTP 200 OK response -> 192.168.4.100
192.168.4.3 -> Fragment 2 of HTTP 200 OK response -> 192.168.4.100
192.168.4.3 -> Fragment 3 of HTTP 200 OK response (PSH) -> 192.168.4.100

192.168.4.3 -> Retransmission of Fragment 3 of HTTP 200 OK response (PSH) -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 1 of HTTP 200 OK response -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 1 of HTTP 200 OK response -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 1 of HTTP 200 OK response -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 1 of HTTP 200 OK response -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 1 of HTTP 200 OK response -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 1 of HTTP 200 OK response -> 192.168.4.100

192.168.4.100 -> ACK of Fragment 1 -> 192.168.4.3

192.168.4.3 -> Retransmission of Fragment 2 of HTTP 200 OK response -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 3 of HTTP 200 OK response (PSH) -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 2 of HTTP 200 OK response -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 2 of HTTP 200 OK response -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 2 of HTTP 200 OK response -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 2 of HTTP 200 OK response -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 2 of HTTP 200 OK response -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 2 of HTTP 200 OK response -> 192.168.4.100

192.168.4.100 -> ACK of Fragment 2 -> 192.168.4.3

192.168.4.3 -> Retransmission of Fragment 3 of HTTP 200 OK response (PSH) -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 3 of HTTP 200 OK response (PSH) -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 3 of HTTP 200 OK response (PSH) -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 3 of HTTP 200 OK response (PSH) -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 3 of HTTP 200 OK response (PSH) -> 192.168.4.100
192.168.4.3 -> Retransmission of Fragment 3 of HTTP 200 OK response (PSH) -> 192.168.4.100

192.168.4.100 -> ACK of Fragment 3 -> 192.168.4.3

这实际上是个大问题,因为在GET请求与最后一个ACK之间大约有40秒的时间差,而这个时间点刚好是应用程序(本例中为telnet)接收数据的时刻。

我检查了所有的校验和,它们都是正确的...

所以我不知道为什么会出现这种情况以及该怎么办!我已经尝试使用不同的操作系统(如Windows 8手机,MAC OSX,Ubuntu 14.04等)作为主机,但仍旧没有改变。如果我从虚拟网络的另一个docker发送相同的请求,一切正常。

有什么关于问题的想法吗?

谢谢!

PS,在这里你可以看到捕获的截图:

enter image description here

更新

我认为有一件有趣的事情是,我进行了类似的捕获,但是当从192.168.4.3发送HTTP请求到192.168.4.100时。捕获再次在192.168.4.100接口上进行,似乎再次显示192.168.4.100忽略它接收到的数据包(例如看三次握手)。我还是找不到原因。

enter image description here


  1. 你是在服务器端还是客户端进行捕获?
  2. 机器之间的 MTU 是多少?
  3. 每个片段的大小是多少?
  4. 响应的大小是多少?
- Malt
我已经编辑了我的帖子,并附上了截图。 - mgaido
你能发布一张带有TCP序列号的截图吗(原始数据包而非重传数据包)?或者更好的方式是,发布实际的pcap文件? 有趣的是,第一个重传的是最后发送的分段(小的那个),比第一个(大的)分段的重传早了200毫秒。 - Malt
抱歉,但是在那个捕获文件中不仅有这些流量,所以我不能分享它。然而,序列号和确认号字段的值就是你可以在截图中看到的(第一个重传的值与之相同...)。我非常仔细地查看了序列号,但是没有发现任何问题。 - mgaido
如果您在Mac上运行Docker,则可能正在运行Boot2Docker,它使用VirtualBox在Linux虚拟机上运行Docker? 因此,请执行“boot2docker ssh”,然后按照上述操作进行。如果您在其他机器上运行Docker,请提供更多详细信息。 - Bryan
显示剩余16条评论
1个回答

2

我解决了我的问题。我在这里发布解决方案,如果有人遇到和我一样的问题,这可能会有用。

问题是我禁用了虚拟桥接口上的TSO(tcp-segmentation-offload),而我的Docker附加到该虚拟桥接口。我使用以下命令:

ethtool -K IFACE_NAME tso off

它仅关闭了TSO,而校验和卸载仍然开启。显然,这会产生一些问题,尽管Wireshark显示TCP校验和正常,但实际上并不是这样。因此,由于TCP校验和错误,主机忽略了该数据包。

要同时关闭TSO和校验和,请使用以下命令:

ethtool --offload IFACE_NAME rx off tx off

现在一切都正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接