我们维护的一个 Web 应用程序最近遇到了一个非常奇怪的问题:两台物理主机上的四台虚拟机中有三台无法通过 HTTPS 连接到我们的支付提供商的服务器。调试这个问题让我对 OSI 堆栈进行了一次有趣的探索:
- 在应用程序级别,HTTPS 请求似乎超时了。
- 使用
openssl s_client
,我发现 SSL 握手失败 - 使用 tcpdump 转储流量并使用 Wireshark 检查,我注意到,对于失败的握手,初始 SYN/ACK 之后来自服务器的所有数据包都具有无效的 TCP 校验和。将数据包内容与成功握手进行比较,我发现至少有一位发生了翻转。然后,服务器尝试重新传输数据包(再次使用无效的校验和)并在 60 秒后关闭连接。
我们的支付提供商和托管公司都无法帮助我们诊断这个问题。幸运的是,这个问题在几个小时后就消失了。
然而,这个“解决方案”让我很不开心。我想知道:
- 造成这种行为的可能原因是什么?
- 如果将来再次出现此问题,如何进一步诊断?
虚拟机在 KVM 上运行 Debian 7。
答案1
因此以这篇文章作为参考:https://www.networkdatapedia.com/single-post/2017/09/13/TCP-Checksum-Error-Case-Study
我将尽力回答并澄清:
- 造成这种行为的可能原因是什么?
可能的原因如下:
- TCP 校验和卸载。如前所述 - 这是一种 CPU 不计算 TCP 校验和而将其留给 NIC 的技术。NIC 可能会计算错误。
- 有故障的 3 层设备。这需要位于 3 层,因为在成功进行以太网 CRC 校验后可能会出现 TCP 校验和错误 - 而 CRC 校验比 TCP 校验和更可靠。因此,您可以排除有故障的电缆或连接器。
- 中间人对数据包有效载荷进行操纵。这种情况不太可能发生,因为中间人能够计算出正确的 TCP 校验和并将其放入数据包中。
- 如果将来再次出现此问题,如何进一步诊断?
使用提到的文章作为参考,您应该设置至少两个流量捕获位置,其中应包括虚拟机以及裸机/路由器接口。
根据网络架构,您可能会发现 L3 网络组件存在故障。不幸的是,网络上游可能存在故障,因此请确保在数据包离开和进入受控环境时捕获它们以确保无误。
就我个人的网络经验而言,完全饱和的网络可能会导致 SSH 或 HTTPS 等协议无法建立连接。确保有足够的可用带宽,并且相关主机能够及时响应。