问题:TCP接收到数据包,但它忽略了它们

我有一个非常奇怪的网络问题。实际的网络配置是相当复杂的,因为我正在使用 Openstack 和 Docker 构建一个虚拟网络。但是,问题不存在,因为我在主机的接口上捕获并且我以正确的方式看到所有数据包....但是由于某些我不知道的原因,似乎 TCP 忽略了它们,尽管它们有已收到:它不会为它们发送 ACK,也不会将数据发送到应用程序。

在我的试验中,我从主机 (192.168.4.100) 向服务器码头 (IP 192.168.4.3) 发送了对 html 页面的 HTTP GET 请求。

我看到使用 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在这里您可以看到捕获的屏幕截图:

在此处输入图像描述

更新

我认为有趣的一件事是我做了一个类似的捕获,但是当一个 HTTP 请求从 192.168.4.3 发送到 192.168.4.100 时。在 192.168.4.100 接口上再次进行捕获,并且 192.168.4.100 似乎再次忽略了它接收到的数据包(例如,查看三向握手)。我又找不到理由了。

在此处输入图像描述

解答

我设法解决了我的问题。我在这里发布解决方案,如果有人遇到我同样的问题,它可能会很有用。

问题是我在我的 Docker 连接到的虚拟网桥上禁用了 TSO(tcp-segmentation-offload),命令如下:

ethtool -K IFACE_NAME tso off

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

要关闭 TSO 和校验和,我只使用了以下命令:

ethtool --offload IFACE_NAME rx off tx off

现在一切正常。

Logo

云原生社区为您提供最前沿的新闻资讯和知识内容

更多推荐