本文已参与「新人创造礼」活动,一同敞开创造之路。

问题背景

该问题案例来自于大众号朋友共享,毛病现象比较少见,简略剖析一下 TCP 三次握手中出现的 RST 衔接问题。

用户反应的问题现象是在客户端经过 curl 拜访 url ,拜访不了,现象必现。

问题剖析

网络拓扑

首要简略了解下网络拓扑,内网环境有多个客户端,经过防火墙出互联网拜访服务器

Wireshark TS | SYN-SYN/ACK-RST 问题

数据包剖析

考虑到用户的问题现象比较明确,直接在问题客户端上经过抓包进行剖析,数据包能够看到明显的反常现象。

Wireshark TS | SYN-SYN/ACK-RST 问题

首要剖析如下:

  1. TCP 握手阶段,以规律性的 SYN-SYN/ACK-RST 进行重复,并未成功建立起衔接;
  2. SYN 重传,每次超时的时刻是 1秒 、2秒 、4秒 、8秒 、16秒
  3. 服务器能正常回来 SYN/ACK,扫除服务端口未翻开问题;
  4. RTT 时刻约 9ms;
  5. 客户端和服务器均支撑 WSOPT 以及 TSOPT;
  6. Seq num 和 Ack num 未见反常;
  7. 客户端自动建议 RST。

考虑到 TCP 三次握手阶段客户端自动建议 RST,那么很有可能与客户端有关,进一步查看,发现 TSOPT 可能有以下问题:

客户端 SYN

Wireshark TS | SYN-SYN/ACK-RST 问题

服务器 SYN/ACK

Wireshark TS | SYN-SYN/ACK-RST 问题

SYN/ACK 中的 TSecr 值 2174718965,不同于 SYN 中 TSval 值 538477964 , 正常情况下应该相同,且 TSval 值为 0 ,疑似造成客户端 RST 。之后尝试在客户端封闭 tcp Timestamp 选项支撑后,客户端 curl 恳求康复正常。

因公网服务器侧无法抓包,因而 SYN/ACK 中的 TSOPT 反常值无法完全定位问题点。可能是服务器,也可能是中间传输设备引起。

TSOPT 值仅在客户端和服务器两端均支撑该选项的情况下,才会在会话中一直带着。上述客户端封闭选项的情况下,则服务器因而也不会发送带有 TSOPT 的数据包 。

RFC 7323

TCP Timestamps option (TSopt):
Kind: 8
Length: 10 bytes

Wireshark TS | SYN-SYN/ACK-RST 问题

Timestamp Value (TSval) . 32 bits.
This field contains the current value of the timestamp clock of the TCP sending the option.

Timestamp Echo Reply (TSecr). 32 bits.
This field is only valid if the ACK bit is set in the TCP header. If it is valid, it echos a timestamp value that was sent by the remote TCP in the TSval field of a Timestamps option. When TSecr is not valid, its value must be zero. The TSecr value will generally be from the most recent Timestamp option that was received; however, there are exceptions that are explained below. A TCP may send the Timestamp option in an initial SYN segment (i.e., segment containing a SYN bit and no ACK bit), and may send a TSopt in other segments only if it received a TSopt in the initial SYN segment for the connection.

扩展剖析

在排障过程傍边,也曾在防火墙衔接互联网侧抓取包,抓取了客户端 2 正常恳求的数据包,如下:

Wireshark TS | SYN-SYN/ACK-RST 问题

此处稍有不同的是,SYN/ACK 中 TSval 和 TSecr 的值均为 0 ,和 RFC 7323 所描述的有所不同,但后续是能够正常建连的。

因为环境已无法复现,仅能推测出是在不同平台上实现的区别,TCP 三次握手阶段部分字段值以 0 替代,像是 ip.id ,或是这儿的 TSval 和 TSecr 。在正常完成三次握手后,相应字段会以实践值持续交互,譬如数据包 6 中的 TSval 和 TSecr 值。

再展现别的两个简略示例

正常两端均支撑 TSOPT 的衔接, 之后交互中均带有 TSOPT 值。

Wireshark TS | SYN-SYN/ACK-RST 问题

仅一端支撑 TSOPT 的衔接,之后交互中并无 TSOPT 值。

Wireshark TS | SYN-SYN/ACK-RST 问题

问题总结

其实说到 RST ,实践上发生 RST 数据包的原因会有很多,暂时整理总结的如下:

  1. 衔接一个未翻开的端口;
  2. 发送到一个已封闭的衔接;
  3. 恳求超时;
  4. socket 选项设置(SO_LINGER);
  5. 应用程序问题;
  6. 反常 SEQ 或 ACK Num ;
  7. 安全策略导致;
  8. 时刻戳问题;
  9. 正常封闭衔接;

总之千奇百怪,需要根据实践环境再做具体剖析。