Wireshark 官网那本《Wireshark User’s Guide》我建议你先别急着翻,真正让大多数人上手的路径,往往是装上软件、选块网卡、点一下开始,然后被满屏的红色蓝色灰色报文直接劝退。但你换个玩法,先理解 OSI 分层、再盯着 TCP 三次握手这几个包看,你会发现 Wireshark 其实没那么神秘,反而像一面能照见网络底层逻辑的镜子。
这篇内容我打算把三件事串在一起讲透:Wireshark 过滤规则怎么用、OSI 模型在抓包界面里到底长什么样、TCP 三次握手的每一个字段变化该怎么读。这三者不是孤立的知识点,而是一条完整的排查链路——用模型定位问题在哪一层,用过滤器把无关流量屏蔽掉,再用握手过程判断连接是否正常。无论你是刚入行的网络运维、做后端开发的工程师,还是正在准备网络技能竞赛的学生,这套组合拳都是最实用的入门路径。
1. 网络排查的核心链路:工具、模型与协议的三方配合
很多新手有个误区,觉得 Wireshark 是“抓包工具”,OSI 是“考试背书的内容”,TCP 三次握手是“面试八股”,三样东西各学各的,最后全忘。实际上,这三者必须组合起来才有意义:OSI 模型告诉你流量在哪一层出问题,Wireshark 让你亲眼看到那一层的数据,TCP 三次握手则是你验证“传输层是否正常”最经典的场景。
1.1 为什么 Wireshark、OSI、三次握手总被放在一起讲
从工作流程来看,网络问题排查通常是这样发生的:用户报告“网页打不开”,你第一反应是猜,是 DNS 解析失败?是 IP 不通?是端口被防火墙拦了?还是服务器根本没监听?这时候 OSI 模型就是一张排查地图,它把整个通信过程切成了七层,你可以从上往下逐层排除,也可以从下往上逐层验证。
但光有地图还不够,你需要一个“显微镜”,也就是 Wireshark。它能把经过网卡的每一个比特还原成人能读懂的报文,包括二层帧头里的 MAC 地址、三层 IP 头里的源和目的地址、四层 TCP 头里的端口号和序号。等你定位到“可能是传输层问题”之后,TCP 三次握手就成了你手里的探针:能不能抓到 SYN?对方有没有回 SYN-ACK?最后的 ACK 有没有发出去?每一步的成败都对应着不同的故障原因。
所以这三者是职责互补的关系。模型负责分层,工具负责取证,协议负责解释“某个行为到底意味着什么”。抓包看到一堆十六进制数据没有意义,但如果你知道以太网帧头之后紧跟的是 IP 头,再往后是 TCP 头,那段十六进制就能被翻译成端口、序号、标志位,整个问题就有了答案。
1.2 这套内容的适用人群和解决的真实问题
我先说结论:只要你需要跟“网络连不上”“接口超时”“数据发不出去”这类问题打交道,这套内容就值得学。后端开发排查接口偶发超时,得看 TCP 握手有没有反复重传;运维排查服务器负载高,得看是不是连接数暴涨导致握手队列溢出;搞 CTF 或者网络技能比赛的,Wireshark 分析 pcap 包几乎是必考项目,过滤规则写不熟练,光在几千个报文里翻就能翻到心态爆炸。
举个例子,一个常见的生产事故:客户端连数据库偶发失败,报错信息只有一句“Connection timed out”。这时候你抓包看,如果发现客户端发了 SYN 之后没有收到任何响应,那大概率是中间网络丢了包,或者服务器端口的连接队列满了直接丢弃了新连接;如果收到了 SYN-ACK 但客户端没发 ACK,那问题可能在客户端本地的防火墙或者内核参数上。这些判断,全都建立在你看得懂三次握手、会用 Wireshark 过滤的基础之上。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Wireshark 过滤规则从入门到实战
Wireshark 最劝退新人的地方,就是抓包很容易,抓到之后无从下手。你只需要开个网页,可能就抓到几千个包,浏览器后台一个 HTTPS 连接、一个 DNS 查询、各种 CDN 节点的通信,全混在一堆报文里。这个时候,过滤规则就是你唯一的救星。
2.1 两类过滤器:抓包过滤与显示过滤
Wireshark 里有两套过滤语法,很多人一开始搞混。
第一类叫抓包过滤(Capture Filter),它在抓包开始之前生效,意思是你告诉 Wireshark“只捕获满足条件的报文”,不满足的干脆不存。这种过滤用的语法比较老,是 pcap 风格的,比如只抓 80 端口流量要写 tcp port 80,只抓某个 IP 要写 host 192.168.1.1。它的好处是节省磁盘空间和 CPU 资源,坏处是你一旦漏掉了条件之外的包,事后没法补救,因为那些包根本没被录下来。
第二类叫显示过滤(Display Filter),它在抓包结束之后、甚至抓包过程中都能用,只影响界面显示,不影响原始数据。也就是说,无论你过滤得多狠,原始报文都在内存里,随时可以换一套过滤条件重新看。显示过滤语法更强大,支持字段级判断,比如查看所有源端口为 443 的包,可以写 tcp.srcport == 443。这套语法是 Wireshark 自己定义的,也是我日常用得最多的一类。
提示:日常排查优先用显示过滤,除非你明确知道要抓哪个端口、哪个 IP,且流量极大,再去用抓包过滤。这样可以避免一次抓包失败后,想再看其他条件时无数据可用。
2.2 最常用的显示过滤表达式
显示过滤的基本结构是 协议.字段 操作符 值。操作符常用的有 ==(等于)、!=(不等于)、>、<,也支持 contains 和 matches 这种字符串匹配。逻辑上可以用 and、or、not 组合条件,也可以用括号调整优先级,比如 http and not tcp.port == 443。
刚刚上手的时候,我建议你把以下几条背下来,它们覆盖了 80% 的日常场景:
| 需求 | 过滤表达式 | 说明 |
|---|---|---|
| 只看某个 IP 的所有流量 | ip.addr == 192.168.1.10 |
ip.addr 同时匹配源和目的,最常用 |
| 只看某两个 IP 之间的通信 | ip.addr == 192.168.1.10 and ip.addr == 192.168.1.20 |
中间用 and 连接 |
| 只看某个 TCP 端口的流量 | tcp.port == 8080 |
同样匹配源和目的端口 |
| 只看 HTTP 协议 | http |
也可以写 `http |
| 只看 DNS 查询和响应 | dns |
包含 DNS 的所有报文 |
| 只看 TCP SYN 包(握手第一步) | tcp.flags.syn == 1 |
后面会细讲 |
| 排除健康检查带来的噪音 | not icmp |
或者 !icmp,过滤掉 Ping 包 |
这些表达式看着简单,但组合起来能解决很多问题。比如你想确定某个服务到底有没有监听端口,抓包后可以直接过滤 tcp.port == 服务端口 and tcp.flags.syn == 1,如果连 SYN 包都没有,说明请求压根没到抓包位置,问题大概率在客户端到服务器这条链路的上游。
2.3 实战:只留下 TCP 握手包的五种写法
TCP 三次握手总共涉及三个报文:SYN、SYN-ACK、ACK。想在 Wireshark 里快速把它们挑出来,直接用 tcp.flags.syn == 1 可以同时命中 SYN 和 SYN-ACK,因为这两个标志位的 SYN 都为 1。如果你还想把最后的 ACK 也包含进来,就得换个思路。
这里我列几种写法,大家按需用:
tcp.flags.syn == 1:得到所有设置了 SYN 标志的包,也就是前两次握手报文。tcp.flags.syn == 1 and tcp.flags.ack == 0:得到纯 SYN 包,即第一次握手。tcp.flags.syn == 1 and tcp.flags.ack == 1:得到 SYN-ACK 包,即第二次握手。tcp.flags.ack == 1:得到所有设置 ACK 的包,数量会很多,不推荐只看这一个条件。tcp.stream eq 0:把某个 TCP 连接(从握手到挥手)的全部报文都拿出来,适合对一次完整会话做分析。
最后一条值得多说两句。Wireshark 会为每次完整的 TCP 连接分配一个流编号,tcp.stream eq 0 表示第一号连接,tcp.stream eq 5 表示第六号,你可以右键任意 TCP 报文,选择“追踪流”自动生成这个过滤条件。分析三次握手时,先用 tcp.stream eq N 把整个连接隔离出来,再按时间顺序看前三个报文,这就是最标准的做法。
3. OSI 七层模型在抓包视角下的真正意义
OSI 参考模型在教科书里被讲成了七个层次的背记口诀,但在抓包的视角下,它不是一个抽象概念,而是报文的真实结构。每一个从网卡捕获进来的包,都默认带着二层帧头、三层 IP 头、四层 TCP 头,你解开多少层头,就能看到对应层的“内容”。
3.1 OSI 七层各层功能与 PDU 对照
OSI 七层从下往上分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。每一层都负责特定职责,也会给自己处理的数据单元起个名字。我直接用表格整理:
| 层次 | 功能职责 | 数据单元(PDU) | 常见协议/设备 |
|---|---|---|---|
| 应用层 | 直接面向用户,提供文件传输、邮件、网页等服务 | 数据 | HTTP、FTP、DNS、SMTP |
| 表示层 | 数据格式转换、加密、压缩 | 数据 | SSL/TLS(实际用在传输层之上) |
| 会话层 | 建立、管理和终止会话 | 数据 | NetBIOS、RPC |
| 传输层 | 端到端连接、可靠传输、流量控制 | 数据段(Segment) | TCP、UDP |
| 网络层 | 逻辑寻址、路由选择 | 数据包(Packet) | IP、ICMP、OSPF |
| 数据链路层 | 物理寻址、封装成帧、差错检测 | 数据帧(Frame) | Ethernet、VLAN、ARP |
| 物理层 | 传输比特流,定义电气、机械特性 | 比特(Bit) | 网线、光纤、集线器 |
考试和面试喜欢问“各层功能”,但实际排查时,你更需要记住的是:越往下越接近硬件,越往上越接近用户。物理层网线没插好,你抓包可能什么都抓不到;数据链路层 MAC 地址不对,STP 环路会把整个二层网络打瘫;网络层 IP 配置错了,三层路由就断了;传输层端口不可达,TCP 握手就永远完不成。
在 Wireshark 里,双击任意一个报文,你会看到协议树一层层展开。最外层是 Frame,表示数据帧的整体信息,包括帧长度和捕获时间;接着是 Ethernet II,对应数据链路层;然后可能看到 IP 头,对应网络层;再往上可能是 TCP 或 UDP,对应传输层;最里面才是应用层协议头,比如 HTTP 报文。这个展开过程,就是 OSI 分层模型最直观的体现。
3.2 OSI 模型与 TCP/IP 模型对照
说实话,现代网络真正跑的是 TCP/IP 协议栈,OSI 是一个参考模型。TCP/IP 模型通常被描述成四层或五层,日常排障我更推荐用五层视角,因为它把经典的“网络接口层”拆成了物理层和数据链路层,跟 Wireshark 里的协议树更能对上。
五层 TCP/IP 模型与 OSI 的对应关系是这样的:
- 应用层,对应 OSI 的应用层、表示层、会话层。HTTP、DNS、FTP 都在这一层。
- 传输层,对应 OSI 传输层。TCP 和 UDP 的端口号、序号就在这里。
- 网络层,对应 OSI 网络层。IP 地址在这里,路由在这里。
- 数据链路层,对应 OSI 数据链路层。MAC 地址、交换机、ARP 在这里。
- 物理层,对应 OSI 物理层。网线、光模块、无线信号在这里。
为什么会有这种不对等?因为 OSI 把会话层和表示层单独抽出来了,但 TCP/IP 协议栈在实践中把它们合进了应用层。你想想,一个 HTTPS 请求,在 Wireshark 里看到的协议栈是 Ethernet -> IP -> TCP -> TLS -> HTTP,根本没有单独的“表示层”字段,因为 TLS 既做了加密又做了数据格式的包装,它被塞在了传输层和应用层之间。
注意:抓包时如果看到协议树里只有 Frame、Ethernet、IP、TCP,没有 HTTP,不要惊讶。TLS 加密后,应用层数据全部加密,Wireshark 无法识别上层协议,除非你配置了解密用的私钥。很多新手抓 HTTPS 看不见“明文 HTTP”,第一反应是抓包失败,其实这只是加密功能在生效。
3.3 在 Wireshark 里看到“分层”这件事
具体怎么在 Wireshark 里把分层“看”出来?我习惯在抓包窗口里点开一个 HTTP 报文,然后把中间面板的协议树展开到最大。你会看到默认列的 Protocol 显示为 HTTP,Info 显示 GET / HTTP/1.1。如果你双击报文,中间面板会一层层列出:
- Frame: 物理层/数据链路层之上的封装信息,告诉你这个帧的总长度是 62 字节,捕获时间是 xx.xx 秒。
- Ethernet II: 源 MAC、目的 MAC、类型字段 0x0800,代表承载了 IPv4。
- Internet Protocol Version 4: 源 IP、目的 IP、协议字段值为 6,代表上层是 TCP。
- Transmission Control Protocol: 源端口、目的端口、序号、确认号、Flags 标志位。
- Hypertext Transfer Protocol: 方法、URI、协议版本、Host 头等。
这一串树形结构其实就是数据封装和解封装的过程。发送方从上往下逐层添加头部,接收方从下往上逐层剥离头部,Wireshark 做的就是“拆封”这份数据包,并且把每一层的头部字段翻译成人类可读的信息。理解这一点后,你再看那些十六进制数据,就不会觉得它们是一堆乱码了。
4. TCP 三次握手逐包拆解
TCP 三次握手是理论课里最经典的内容,但真到了抓包分析的时候,如果你只看 Wireshark 里三行带颜色的报文,很容易忽略关键细节。三次握手不是三个孤立的包,而是一组带有严格序号规则的状态交互,每一步的 seq、ack 变化都暗藏信息。
4.1 三次握手每一步的报文细节
我们先设定一个场景:客户端 IP 是 A,端口是 52000,服务器 IP 是 B,端口是 80。客户端发起连接时,Wireshark 会依次捕获到三个报文:
第一次握手,客户端向服务器发送 SYN 报文。在 Wireshark 里打开这个包,看 TCP 头的 Flags,你会发现 SYN 位为 1。这个包的特点是:不携带任何应用层数据,序号(Sequence Number)是一个随机初始值,我们称之为 x。注意,很多人困惑为什么 seq 是一个很大的数字,比如 3680899906,而不是从 0 开始。因为 TCP 出于安全考虑,初始序号不是 0,而是由操作系统随机生成的 ISN(Initial Sequence Number),防止旧连接中的延迟报文被误认为是新连接的合法报文。
第二次握手,服务器收到 SYN 后,如果同意建立连接,就回复 SYN-ACK 报文。这个包的 Flags 里 SYN 和 ACK 同时为 1。它的确认号(Acknowledgment Number)是 x+1,意思就是“我收到了你的 SYN 序号 x,接下来我期待你发送序号为 x+1 的数据”。与此同时,服务器也会给出自己的初始序号 y,存放在 Sequence Number 字段里。所以第二次握手其实是“捎带”了两个功能:一个是对客户端 SYN 的确认,一个是服务器自己的 SYN。
第三次握手,客户端收到 SYN-ACK 后,回复一个 ACK 报文。这个包 Flags 里只有 ACK 为 1,确认号是 y+1,意思是“我收到了你的序号 y,接下来请你从 y+1 开始发数据”。三次握手到这里就完成了,连接建立,双方进入 ESTABLISHED 状态,之后就可以开始传输 HTTP 请求和响应。
我把这组关键字段的对应关系整理成一张表,方便你对照分析:
| 次数 | 报文方向 | 标志位 | 序号(seq) | 确认号(ack) | 含义 |
|---|---|---|---|---|---|
| 第 1 次 | A → B | SYN | x | 无 | A 请求建立连接 |
| 第 2 次 | B → A | SYN, ACK | y | x+1 | B 同意并确认 A 的同步 |
| 第 3 次 | A → B | ACK | x+1 | y+1 | A 确认 B 的同步 |
Wireshark 里抓到的 seq/ack 数值往往是相对值。默认情况下,Wireshark 会把第一个可见报文的 seq 显示成相对序号,也就是从 0 开始,这样便于阅读。如果切换到绝对序号,你会看到真实的那串随机数字。这个设置在“Preferences -> Protocols -> TCP -> Relative sequence numbers”里可以改。新手不必纠结绝对序号,相对序号反而更容易理解三次握手的逻辑。
4.2 为什么必须是三次握手
关于“为什么是三次而不是两次”,网上的解释很多,但我觉得最直观的思考方式是把它当成一次“双方互测收发能力”的过程。
第一次握手结束后,服务器知道了一个事实:客户端能发包,而且客户端发出的包能到达服务器。但客户端还什么都不知道,它不确定自己发出的包是否真的能到服务器,也不确定服务器是否在线。
第二次握手结束后,客户端知道了两个事实:服务器能收到包,服务器也能发包。同时客户端还拿到了服务器的初始序号,之后可以按序号通信。但服务器自己依然不确定“自己发出的 SYN-ACK 是否被客户端收到了”。
第三次握手结束后,服务器知道了两个事实:客户端能收到服务器发出的包,而且客户端已经准备好进入数据通信状态。到了这一步,双方都确认了“对方能收、自己能发、序号已经同步”,连接才真正建立。
如果只握手两次,会出现一个经典问题:如果客户端第一次发送的 SYN 在网络中延迟,客户端超时后重发了一个新的 SYN,服务器基于第二次 SYN 建立了连接,但随后第一次的旧 SYN 又到达了服务器,服务器不知道这是旧报文,再次建立连接,结果就在服务器侧白白浪费了一个连接。三次握手通过客户端在收到 SYN-ACK 之后,必须再确认一次序号,来消除这种“旧的重复连接请求”带来的歧义。
还有一种问法是“为什么不是四次”,因为第三次 ACK 已经足够让双方确认收发能力得到同步,四次只会多一次无效往返。TCP 设计的哲学是“够用就行”,三次正好完成序号同步,多了就是浪费。
4.3 实操:用 Wireshark 抓一次完整的 HTTP 握手
纸上谈兵没意思,我带你把整个流程走一遍。前提是你本机装了 Wireshark,并且能访问一个 HTTP 网站。以前访问 http://example.com 这样不加密的站会更方便看到 HTTP 报文,但现在很多用 HTTPS,握手后应用层就被加密了。为了看三次握手,其实 HTTPS 也一样能看,因为 TCP 握手在 TLS 加密之前发生,抓包完全不受影响。如果你想同时看清 HTTP 内容,我建议本地起一个简单的 HTTP 服务,比如 Python 写几行代码:
python复制import http.server
import socketserver
handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("127.0.0.1", 8080), handler) as httpd:
httpd.serve_forever()
然后打开 Wireshark,选择 Loopback 网卡(本地回环接口),因为访问 127.0.0.1 的流量只会经过这个接口。点击开始捕获,再用浏览器访问 http://127.0.0.1:8080,随便点几个文件。停止抓包,在过滤栏输入 tcp.port == 8080,就能看到从 TCP 握手到 HTTP 请求、响应再到挥手的所有报文。
按时间顺序找前三个报文,正常情况下就是三次握手。为了放大细节,点开第一个 SYN 包,看 TCP 层的 Flags,你会看到 SYN 位是 1,Sequence Number 是 0(相对序号)。点开第二个包,Flags 里 SYN 和 ACK 都是 1,Sequence Number 是 0,Acknowledgment Number 是 1(相对值)。点开第三个包,只有 ACK,确认号也是 1。这三个报文中间往往有毫秒级的时间间隔,如果发现第一个包和第二个包之间间隔很长,说明服务器侧的连接队列可能存在问题。
提示:抓本地回环包时,Wireshark 里显示的源 MAC 和目的 MAC 全是 00:00:00:00:00:00,这很正常,回环接口不存在真实的以太网帧,看到空 MAC 不代表抓包有问题。
5. 常见问题与排查技巧实录
最后这部分我整理一下实操中最容易踩的坑,以及遇到三次握手中断时该怎么定位。这些都是我平时排查问题时的真实记录,希望能帮你少走弯路。
5.1 抓包阶段的高频坑
新手第一次用 Wireshark 最常见的疑问是“我能看到别人的流量吗?”答案是:取决于你所处的网络环境。在普通接入交换机的网段里,交换机只会把数据帧转发给目的 MAC 地址对应的端口,你的网卡默认只能看到发给自己的广播帧和单播帧。要看到同网段其他人的流量,需要把网卡设置为混杂模式(Promiscuous Mode),同时交换机需要做端口镜像或利用类似 HUB 的物理结构。在 Wireshark 里可以通过“Capture Options”勾选混杂模式,但能不能抓到别人的包,最终还是取决于上游设备是否把流量送到了你的网卡。
还有一个坑是“抓不到本地回环流量”。默认情况下,Wireshark 需要选择 Loopback: lo 或者 VirtualBox Host-Only Network 这样的接口来抓本机进程之间的通信。如果选错了物理网卡,本机进程去访问 127.0.0.1 时,流量根本不会经过物理网卡,自然抓不到。
关于过滤语法报错,Wireshark 会把无效表达式背景标成红色,有效表达式背景是绿色。很多人没注意这个颜色提示,写错语法还一脸懵。比如 ip.addr = 192.168.1.1 就错了,必须用 ==,因为这是比较运算而不是赋值。
5.2 三次握手异常时怎么判断问题出在哪
三次握手是非常好用的故障定位工具。我总结了几种典型情况:
| 抓包现象 | 可能的故障点 | 下一步排查方向 |
|---|---|---|
| 客户端只发 SYN,收不到 SYN-ACK | 中间网络丢包、服务器端口未监听、防火墙丢弃 | 用 telnet 或 nc 测端口;检查服务器接入层防火墙 |
| 客户端收到 SYN-ACK,但不发 ACK | 客户端本机防火墙拦截、客户端内核参数问题 | 检查客户端 iptables 或防火墙规则 |
| 客户端不断重发 SYN | 网络延迟或丢包严重、服务器 accept 队列满 | ping 看连通性;在服务器看 ss -lnt 的 Send-Q/Recv-Q 是否积压 |
| 握手完成但立即 RST | 端口服务拒绝、应用层主动断开 | 看 RST 包的方向,可能是协议不匹配或服务报错 |
有一种非常常见的场景:客户端连接一个服务,服务器端口的 Listen 队列已满。TCP 协议栈收到新连接后,如果 accept 队列没有空间,就会直接丢弃 SYN 包,客户端表现为不断重发 SYN,每次重发间隔指数退避(1s、2s、4s...),而服务器上你可能看不到任何应用日志,因为应用进程还没成功 accept 到新连接。这时候抓包是最直观的确认手段:服务器侧抓不到入站 SYN,或者抓到了但没回 SYN-ACK,问题就在服务器的队列或防火墙。
另外,公司环境或者云服务器通常默认有防火墙策略,比如仅放行 80/443,而 3306 数据端口被限制。这种情况下客户端连接 MySQL 会一直卡在 TCP 握手阶段,表现为 SYN 发出,对端没有回应。用 Wireshark 抓包后,如果确认 SYN 已经发出但对方没有 SYN-ACK,优先检查安全组和防火墙,而不是急着去调 MySQL 配置。
5.3 对新手最有用的三条建议
第一,抓包范围越小越好。不要一上来就抓全网的流量,先想清楚自己要验证什么问题。只分析 SSH 登录慢,就过滤 tcp.port == 22;只排查 HTTP 接口偶发超时,就过滤 tcp.port == 服务端口。报文越少,越容易看清事件脉络。
第二,多利用 Wireshark 的“追踪流”功能。右键任意 TCP 报文,选择“追踪流 -> TCP 流”,Wireshark 会自动生成 tcp.stream eq N 的过滤条件,并把你带到一个只包含该连接所有报文的视图。这是分析一次完整请求最简单的方法,比手写几百字符的过滤表达式高效太多。
第三,结合状态统计功能看宏观趋势。比如“Statistics -> TCP Stream Graphs -> Time-Sequence Graph”可以画出 TCP 序号随时间的变化,如果出现平台期说明有重传和拥塞;“Statistics -> I/O Graph”可以看流量吞吐量随时间的变化,适用于定位突发流量。这些高级功能不一定入门就要会,但在你抓包熟练之后,它们能帮你看懂更多问题。
我个人的体会是,Wireshark 过滤规则、OSI 模型和 TCP 三次握手这三块内容,本质上是一套“结构化思维”的训练。模型让你不慌,过滤让你精准,握手让你确认。每次排障别急着瞎猜,先把抓手落在具体层上,再用报文说话,网络问题大多都能定位得八九不离十。
