Wireshark抓tcp包实践与深入了解存活机制

Wireshark抓tcp包实践与深入了解存活机制

Aoi Komiya Lv3

前言

最近两次面试都有面试官看我简历上写的博客其实还挺高兴的。

然后想到最近春招面试被问到很多次TCP的八股题,今晚尝试用wireshark抓包看一看。也算是水一篇博客了。

Web服务

尝试用wireshark抓本机访问公网的包发现http.request.method == "GET" 过滤后没有结果,忘了现在已经普及HTTPS了hhh。

想明白这点后马上打开学校内网的教务系统,因为它没做HTTPS,再加上我Firefox设置了HTTPS严格模式,每次用我都要点一下【继续不安全访问】,这是我第一反应想到的HTTP网站hhh

但是其实看起来还挺吃力的,索性就自己写个web服务看一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import (
"fmt"
"net/http"
)

func webhook(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "TCP")
}

func main() {
http.HandleFunc("/webhook", webhook)
fmt.Println("Server on.")
if err := http.ListenAndServe(":8080", nil); err != nil {
fmt.Printf("Error: %v\n", err)
}
}

Wireshark 配置 环回适配器

因为webhook是在本地8080端口上运行的,所以打开wireshark配置Capture Option 要选择为 Adapter for loopback traffic capture(环回适配器),Windows 内置的 环回适配器(Loopback Pseudo-Interface),用于捕获 本机内部的网络流量(如 localhost 通信),数据不经过物理网卡,直接在内核层转发。

capture_option

抓包

按照以下步骤开始抓包

  1. 运行webhook服务

  2. 启动wireshark抓包

  3. 浏览器访问localhost:8080

此刻可以wireshark中抓到许多包,输入以下过滤器语法来过滤数据包。我这里多写了个and条件,直接筛选Info 列的/webhook api接口

1
http.request.method == GET && frame contains "webhook"

过滤后如下图,这不比抓公网的包清楚。

webhook

wireshark能够抓到多层网络协议的报文。由于我是在本地起的web服务,在配置wireshark的Capture Option时选择了Adapter for loopback traffic capture(环回适配器),如下图,是没有链路层的报文的。

依次分别为Frame物理层,链路层、Internet Protocol网络层、Transmission传输层、明文数据。

loopback

TCP 流分析

选中第一个时间更早的数据包,使用”Following TCP streams”功能跟踪tcp数据流

tcp_follow1

可以看到完整的TCP连接与关闭数据流:

tcp_follow2

本质上”Following TCP streams”的功能,就是使用tcp.stream eq xx的过滤语法,xx是具体的 TCP 流编号,上图中 TCP 流编号是56。Wireshark 会为每个 TCP 连接分配一个唯一的流编号(tcp.stream),方便对不同的 TCP 连接进行区分和分析。

TCP 三次握手

如下图红框中,前三个数据包是TCP的握手数据包,可以看到明显的ACK SYN标志位和seq值:

tcp_link

第一个数据包Seq=0,客户端初始序列号。

第二个数据包Info 列显示 [SYN, ACK],表示服务器确认客户端请求并同步自身序列号。

  • 确认号(Ack)Ack=1,即确认客户端序列号 Seq=0,期望下一个包序列号为 1
  • 序列号(Seq)Seq=0,服务器初始序列号。

第三个数据包Info 列显示 [ACK],表示客户端确认服务器响应。

  • 确认号(Ack)Ack=1,确认服务器序列号 Seq=0

  • 序列号(Seq)Seq=1,基于第一次握手的 Seq=0 递增。

TCP 存活探测 探讨与实践

TCP连接建立后,可以看到后续是一些该TCP连接的存活探测数据包,即标有 [TCP Keep-Alive] 的数据包。

这些数据包在长达一分钟的时间能不断发送,一分钟后TCP执行四次挥手断开连接。

这里其实有个小的细节,以前一直没有注意,背八股也没有注意到。

[TCP Keep-Alive] 的存活探测数据包发送多久时间,一方面是由系统层面的 TCP 保活机制确定保活参数。

  • linux下默认保活时间由 net.ipv4.tcp_keepalive_time参数决定(默认 2 小时)
  • win下由注册表参数决定,可以查找对应注册表键值,也可以使用terminal命令快速查找(若没有设置KeepAliveTime 字段,则该字段值设为默认值7200000毫秒,即2小时)

tcp保活

既然知道了OS层面的保活时间,跟我们实际观测到的TCP保活时间是对不上的。实际保活时间只有1分钟。

原因在于,[TCP Keep-Alive] 的存活探测数据包发送多久时间,另一方面还由HTTP 层的长连接机制决定。而浏览器默认启用 Connection: keep-alive,空闲超时通常为 1 分钟(如 IE/Edge 注册表默认值 KeepAliveTimeout=60000 毫秒)。

虽然我都背过计网经典八股 – HTTP/1.1版本支持长连接了,但具体实践过后,才能有更加深刻的印象……

TCP 四次挥手

拉到整个TCP流的最后,是TCP的挥手包,如下图所示:

tcp_unlink

注意看最后哦6条数据包,其中两行黑色的根据[TCP Dup ACK xxx#y] 标签可以判断是之前xxx号包的第y次 重复的 TCP 确认报文(Duplicate ACK)。剩下四行是56流编号TCP连接的四次挥手包。

可以很明显地看到八股吟唱中的常见语句[FIN ACK] 标签,各个包的Seq值与其后续包的Ack值也能对上。

后记

本次实践源于等腾讯三面心太累,又不想背八股,索性找点事情玩玩。

Just for fun.

如能给一些朋友作为参考帮助,不甚荣幸。

  • Title: Wireshark抓tcp包实践与深入了解存活机制
  • Author: Aoi Komiya
  • Created at: 2025-03-15 23:15:02
  • Updated at: 2025-03-16 10:51:31
  • Link: https://blog.komiya.monster/2025/03/15/wireshark_tcp/
  • License: This work is licensed under CC BY-NC-SA 4.0.