Wireshark TS | 惊,客户端居然睡着了

3,055 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

问题背景

容我也标题党一下,该用户反馈服务器偶发错误,无法收到某个客户端所发送的数据,通过抓包查看 TCP 三次握手正常,但由于某种原因服务器会重新发送 SYN/ACK,之后会通过 FIN 来关闭连接,因此用户怀疑服务器网络或是其他出现问题。

案例取自 Wireshark 官方问答论坛

osqa-ask.wireshark.org/questions/4…

问题分析

服务器端

简要分析如下:

  1. TCP 三次握手正常,IRTT 0.004858 s ;
  2. 客户端毫无反应,服务器在 31s 之后重新发送了 SYN/ACK 用来确认客户端是否还存活;
  3. 神奇的是客户端还在,协议栈层面返回了一个 ACK ;
  4. 但之后整个交互又陷入沉寂,服务器在 20s 之后无法忍受,发送了 FIN ,客户端仍能响应确认 ACK 。

客户端

简要分析如下:

  1. 整体现象与服务器端基本一致;
  2. TCP 三次握手正常,IRTT 0.005896 s ;
  3. 客户端在 TCP 三次握手完成后,并无请求发出,并在 31s 之后接收到了服务器重发的 SYN/ACK ,返回确认 ACK ;
  4. 之后一直无交互,客户端又在 20s 后收到了服务器发送的 FIN ,继续响应确认 ACK ;
  5. 由于 TCP 双向通讯,四次挥手仅完成一半,客户端在长达 1651s 之后才发起了 POST 请求,之后才发送自己的 FIN,且由于得不到确认,客户端不断进行重发 POST 请求。

补充

在该帖的交流中,用户也曾补充了客户端正常请求下的数据包图,从图片中可得知,客户端正常会在 2ms 之后发起 POST 请求,此后交互正常至 FIN 结束。

同样另外一个延迟请求的数据包,客户端会在 POST 请求超大延时发出后,得到服务器 RST 响应。

总结

结合上述数据包的分析结果,从我个人角度来说,实际上在客户端和服务器端均有一定的异常行为,如下:

  1. 客户端,确实如分析所说,像是睡着了,陷入一种沉寂状态,POST 请求严重滞后,这也是此案例中需重点排查的一方面;
  2. 服务器端,在讨论中并没有关注服务器端的行为,但些许疑惑的是,SYN/ACK 的重传行为以及 31s 的由来;
  • 考虑到该用户强调抓包文件确实是在服务器上所抓取,所以可以确认的是服务器端收到了 TCP 握手第三次数据包,但 SYN/ACK 的重传行为,像是 TCP 三次握手并没有实际完成。如果假设服务器端开启了 TCP 选项 TCP_DEFER_ACCEPT ,因此并未正常建立连接,同样等待客户端发送 POST 数据请求,但服务器端未正常收到,所以之后进行了 SYN/ACK 的重传。
  • 如果只是考虑 SYN/ACK 重传行为,确实以 TCP_DEFER_ACCEPT 解释会更加合理,但结合 31s 的时间,又会带来新的疑问。假设由于net.ipv4.tcp_synack_retries的行为,第 1 次重试发生在 1 秒后,接着会以翻倍的方式在第 2、4、8、16 秒等做 5 次重试,但实际上只有在 31s 之后才抓取到一次 SYN/ACK 重传。这种情况更像是端到端通讯中,存在类似代理、负载均衡之类的设备(🤣 合理假设)

TCP_DEFER_ACCEPT ,可以参考之前的一篇文章 《Wireshark TS | 服务器在三次握手后发送RST ?!》

该案例来自互联网,虽然场景和真相已无从考证,但从网络数据包研究来说,合理的判断和分析总是一个很有乐趣并能不断提高的过程。