背景

来自于 Wireshark 新版本 3.6.0 的功能说明,详见 : Wireshark 3.6.0 Released ,摘引如下:

TCP conversations now support a completeness criteria, which facilitates the identification of TCP streams having any of opening or closing handshakes, a payload, in any combination. It can be accessed with the new tcp.completeness filter.

TCP 会话目前支持完整性策略,对于分析 TCP 流有着很方便的帮助作用。可以通过 tcp.completeness 显示过滤器表达式进行相关过滤。

TCP 会话完整性

什么是 TCP 会话完整性 ? TCP Conversation Completeness ,理论上一个完整的 TCP 会话应该同时包含最常理解的打开握手和关闭握手,而并不依赖于有或者没有任何数据传输。

但考虑到实际大多数 TCP 会话场景,包含数据更多才像是一次完整会话,因此可以通过以下 tcp.completeness 字段来构建会话过滤值:

  • 1 : SYN
  • 2 : SYN-ACK
  • 4 : ACK
  • 8 : DATA
  • 16 : FIN
  • 32 : RST

以上字段值可以灵活组合,最终形成不同的 TCP会话完整性 显示过滤表达式。

实例分析

TCP 三次握手

举例来说,如果想在数据包文件中过滤出一个仅包含标准 TCP 三次握手的会话,那么可以使用表达式 'tcp.completeness==7' ,因为 1 (SYN) + 2 (SYN/ACK) + 4 (ACK) = 7 。

wireshark tcp ack和seq号 wireshark tcp stream_网络协议

数据包详细示图中的显示

wireshark tcp ack和seq号 wireshark tcp stream_网络_02

需要特别注意的是,该 TCP Steam 90 仅有 TCP 三次握手的数据包,可以再次过滤 tcp.stream 验证。

wireshark tcp ack和seq号 wireshark tcp stream_网络协议_03

所以如果在某条 TCP 流中包含有任何非 TCP 三次握手的数据包时,表达式 'tcp.completeness==7' 是不生效,即无法过滤出该条 TCP 流。

提前以一个完整 TCP 流的示例说明,该 TCP 流包含 TCP 三次握手、数据、TCP 四次挥手完整数据包。

wireshark tcp ack和seq号 wireshark tcp stream_网络_04

而应用表达式 'tcp.completeness==7' ,是无法过滤出任何数据包的。

wireshark tcp ack和seq号 wireshark tcp stream_网络协议_05

之前写过的一篇文章《快速显示过滤之 TCP 三次握手》,相较新版本 TCP 完整性会话的过滤方式侧重点不同,前篇文章更多是为了解决 TCP 三次握手中第三个 ACK 的过滤问题。



TCP 四次挥手

同样,如果想在数据文件中过滤出一个仅包含标准 TCP 四次挥手的会话,那么可以使用表达式 'tcp.completeness==20' ,因为 4 (ACK) + 16 (FIN)= 20 。

wireshark tcp ack和seq号 wireshark tcp stream_网络_06

数据包详细示图中的显示

wireshark tcp ack和seq号 wireshark tcp stream_wireshark_07

同样需要特别注意的是,这里为什么使用表达式 'tcp.completeness==20' ,而不是使用表达式 'tcp.completeness==16' ,这也是在标准 TCP 四次挥手上理论和实际上的有所不同,有兴趣的同学可以发散思考下。



TCP RST 关闭握手

在 TCP 会话关闭连接的方式,可以通过 FIN ,也可以通过 RST 。简单以一个连接对端未开通端口的示例,如下

wireshark tcp ack和seq号 wireshark tcp stream_tcpdump_08

同样此处使用的表达式是 'tcp.completeness==37' ,1 (SYN) + 4 (ACK) + 32 (RST)= 37 。



TCP 完整会话

最后回到真正的 TCP 会话案例,一个完整的带有数据传输的会话将通过一个更多组合的表达式被过滤,考虑到关闭连接可以与 FIN 或 RST 数据包关联,甚至说两者都关联的情况,最完整的过滤表达式为:

tcp.completeness == 31 or tcp.completeness == 47 or tcp.completeness == 63

考虑到展示方便,以下分别单独就 3 个表达式做简单示例。


最标准的 TCP 完整会话, 'tcp.completeness==31' ,因为 1 (SYN) + 2 (SYN/ACK) + 4 (ACK) + 8 (DATA) + 16 (FIN)= 31 。

wireshark tcp ack和seq号 wireshark tcp stream_网络_09

以 RST 方式关闭连接的 TCP 完整会话, 'tcp.completeness==47' ,因为 1 (SYN) + 2 (SYN/ACK) + 4 (ACK) + 8 (DATA) + 32 (RST)= 47 。

wireshark tcp ack和seq号 wireshark tcp stream_网络协议_10

FIN + RST 同时存在的 TCP 完整会话, 'tcp.completeness==63' ,因为 1 (SYN) + 2 (SYN/ACK) + 4 (ACK) + 8 (DATA) + 16 (FIN)+ 32 (RST)= 63 。

wireshark tcp ack和seq号 wireshark tcp stream_网络_11


总结

综上所述,TCP 会话的完整性策略检查,对于分析处理 TCP 流带来很大的便捷性,故障排查方面又一个很好的技巧。