2. 网络抓包基础:Wireshark/Tcpdump的安装与基本使用、抓包过滤器与显示过滤器、理解三次握手与四次挥手

网络抓包,说白了就是给网络通信装个「监控探头」。你想想看,当用户反馈「页面打不开」或者「接口响应慢」的时候,光靠猜是没用的。抓包能让你看到最原始的数据包,谁发的、发给谁、发了什么、对方回了什么,一目了然。

我个人习惯,不管排查什么问题,第一件事就是先抓个包看看。很多时候,问题在抓包后几分钟内就能定位,根本不用去翻代码。

2.1 抓包工具安装与基础使用

工欲善其事,必先利其器。Wireshark 和 Tcpdump 是网络排查的两把「瑞士军刀」。一个图形化,一个命令行,各有各的适用场景。

2.1.1 Wireshark 安装

Wireshark 适合在桌面环境使用,安装过程很简单,但有几个坑要注意。

操作系统 安装方式 注意事项
Windows 官网下载 exe 安装包,一路 Next 安装时会提示安装 WinPcap 或 Npcap,必须选 Npcap(WinPcap 已停止维护)
macOS brew install --cask wireshark 安装后需要授权网络权限,否则抓不到包
Linux sudo apt install wireshark 或 yum install wireshark 安装后需要将用户加入 wireshark 组:sudo usermod -aG wireshark $USER
我曾经踩过的坑:在 Windows 上装 Wireshark 时没注意,默认选了 WinPcap。结果抓包时发现只能抓到本机发出的包,收不到任何响应。折腾了半天,换成 Npcap 就好了。所以,Windows 用户务必选 Npcap。

2.1.2 Tcpdump 安装

Tcpdump 是命令行工具,适合在服务器上使用。服务器没有图形界面,Wireshark 用不了,Tcpdump 就是首选。

# CentOS / RHEL
sudo yum install -y tcpdump

# Ubuntu / Debian
sudo apt install -y tcpdump

# macOS(自带,但版本较老,建议用 brew 更新)
brew install tcpdump

安装完成后,验证一下:

tcpdump --version

能看到版本号,说明安装成功。

2.1.3 基础抓包操作

先看 Wireshark 的用法。打开 Wireshark,你会看到一堆网卡列表。选对网卡是关键——如果你要抓服务器的流量,却选了无线网卡,那肯定什么都抓不到。

我建议你记住几个快捷键:

  • Ctrl + E:开始/停止抓包
  • Ctrl + K:重新选择抓包网卡
  • Ctrl + .:在抓包过程中快速应用显示过滤器

Tcpdump 的基本用法:

# 抓取 eth0 网卡的所有流量
sudo tcpdump -i eth0

# 抓取 100 个包后自动停止
sudo tcpdump -i eth0 -c 100

# 将抓包结果保存到文件,方便后续分析
sudo tcpdump -i eth0 -w capture.pcap

# 读取保存的抓包文件
tcpdump -r capture.pcap
小技巧:在服务器上抓包时,我习惯用 -w 参数把包保存下来,然后用 scp 传到本地用 Wireshark 分析。Wireshark 的图形化分析能力比 Tcpdump 强太多了,尤其是看 TCP 流和统计信息的时候。

2.2 抓包过滤器与显示过滤器

很多新手一打开 Wireshark,看到满屏花花绿绿的包就懵了。别慌,过滤器就是用来「去粗取精」的。Wireshark 有两种过滤器,很多人搞混,我帮你理清楚。

类型 作用时机 语法 典型场景
抓包过滤器 抓包之前设置,只抓符合条件的包 BPF(Berkeley Packet Filter)语法 只抓 80 端口的流量,减少抓包文件大小
显示过滤器 抓包之后设置,从已抓到的包中筛选 Wireshark 专有语法 从大量包中只看某个 IP 的通信

2.2.1 抓包过滤器(Capture Filter)

抓包过滤器在数据包进入 Wireshark 之前就生效了。它的好处是节省资源——如果你只关心 HTTP 流量,就别把 SSH、DNS 的包也抓进来。

常用的抓包过滤器写法:

# 只抓 80 端口的流量(HTTP)
port 80

# 只抓来自或发往 192.168.1.1 的流量
host 192.168.1.1

# 只抓 192.168.1.0/24 网段的流量
net 192.168.1.0/24

# 只抓 TCP 协议
tcp

# 组合条件:抓 80 端口且来自 192.168.1.1
host 192.168.1.1 and port 80

Tcpdump 中同样使用 BPF 语法:

sudo tcpdump -i eth0 port 80
sudo tcpdump -i eth0 host 192.168.1.1
sudo tcpdump -i eth0 'tcp and port 443'
核心要点:抓包过滤器是「事前过滤」,一旦设置,没被匹配的包根本不会进入内存。这在流量很大的服务器上特别有用——我曾经在线上服务器抓包,如果不加过滤器,几秒钟就能生成几个 GB 的文件,磁盘直接写满。

2.2.2 显示过滤器(Display Filter)

显示过滤器是「事后过滤」。包已经抓下来了,你想怎么看就怎么看。Wireshark 的显示过滤器语法更丰富,也更灵活。

常用的显示过滤器:

# 只看 HTTP 协议
http

# 只看源 IP 为 192.168.1.1 的包
ip.src == 192.168.1.1

# 只看目的端口为 443 的包
tcp.dstport == 443

# 只看 TCP 三次握手的 SYN 包
tcp.flags.syn == 1 and tcp.flags.ack == 0

# 只看重传包
tcp.analysis.retransmission

# 只看延迟大于 200ms 的包
tcp.analysis.ack_rtt > 0.2

在 Wireshark 里,你可以在顶部的过滤栏直接输入这些表达式。输入时会有自动补全,非常方便。

我的习惯:在服务器上用 Tcpdump 抓包时,我会用抓包过滤器只抓目标端口(比如 port 8080),减少文件大小。然后把文件拉到本地,用 Wireshark 打开,再用显示过滤器做精细分析。这样既节省服务器资源,又能充分利用 Wireshark 的分析能力。

2.3 理解三次握手与四次挥手

TCP 是可靠的传输协议,它的可靠性建立在「连接管理」上。三次握手建立连接,四次挥手断开连接。这两个过程,是网络排查中最常看的东西。

2.3.1 三次握手:建立连接

为什么叫「三次」握手?因为需要三次报文交换才能确认双方都能收发数据。你想想看,如果只有两次,客户端怎么知道服务器已经收到了自己的请求?

流程是这样的:

  1. 客户端 → 服务器:SYN(Seq=x)
    客户端说:「我要连接你,我的初始序列号是 x」
  2. 服务器 → 客户端:SYN + ACK(Seq=y, Ack=x+1)
    服务器说:「收到,我的初始序列号是 y,我期待你下一个包序号是 x+1」
  3. 客户端 → 服务器:ACK(Seq=x+1, Ack=y+1)
    客户端说:「收到你的确认,我期待你下一个包序号是 y+1」

在 Wireshark 里看三次握手,你会看到三个包:

1. 192.168.1.2 → 10.0.0.1  TCP  SYN  Seq=0
2. 10.0.0.1 → 192.168.1.2  TCP  SYN, ACK  Seq=0, Ack=1
3. 192.168.1.2 → 10.0.0.1  TCP  ACK  Seq=1, Ack=1
注意:Wireshark 显示的 Seq 默认是「相对序列号」(Relative Sequence Number),从 0 开始。如果你想看真实的绝对序列号,可以在 Wireshark 的 Preferences → Protocols → TCP 里取消勾选「Relative sequence numbers」。

2.3.2 四次挥手:断开连接

断开连接需要四次,因为 TCP 是「全双工」的——双方都可以独立地关闭自己的发送通道。

  1. 客户端 → 服务器:FIN(Seq=u)
    客户端说:「我不再发数据了」
  2. 服务器 → 客户端:ACK(Seq=v, Ack=u+1)
    服务器说:「收到,但我还有数据要发」
  3. 服务器 → 客户端:FIN(Seq=w, Ack=u+1)
    服务器说:「我的数据也发完了,可以关了」
  4. 客户端 → 服务器:ACK(Seq=u+1, Ack=w+1)
    客户端说:「收到,关闭吧」

这里有个常见问题:为什么客户端最后还要等 2MSL(Maximum Segment Lifetime)才彻底关闭?

嗯,这是为了防止最后一个 ACK 丢失。如果服务器没收到 ACK,会重发 FIN,客户端需要能再次响应。2MSL 的时间足够让网络中所有残留的报文段都消失。

2.3.3 抓包实战:看三次握手和四次挥手

我们来实际操作一下。打开终端,用 Tcpdump 抓一个 HTTP 请求:

# 终端1:开始抓包
sudo tcpdump -i any -w handshake.pcap port 80

# 终端2:发起 HTTP 请求
curl http://example.com

# 回到终端1,按 Ctrl+C 停止抓包
# 用 Wireshark 打开 handshake.pcap

在 Wireshark 里,输入显示过滤器 tcp.flags.syn == 1,就能看到三次握手的 SYN 包。再输入 tcp.flags.fin == 1,就能看到四次挥手的 FIN 包。

我建议你重点关注几个指标:

  • SYN 到 SYN+ACK 的时间:如果这个时间很长,说明服务器处理连接请求慢,可能是服务器负载高或者内核参数有问题
  • FIN 到 ACK 的时间:如果这个时间很长,说明应用层没有及时调用 close(),可能是代码有 bug
  • 是否有 RST 包:RST 表示异常断开,通常意味着程序崩溃或者端口未监听
避坑指南:我曾经排查过一个线上问题,客户端频繁报「Connection reset by peer」。抓包后发现,服务器在三次握手完成后,立即发送了 RST。原因是服务器端的 backlog 队列满了,内核直接拒绝了连接。调整了 net.core.somaxconn 和应用的 listen backlog 参数后,问题解决。

2.4 本章知识体系

下面这张图帮你梳理本章的核心知识点,建议保存下来,以后排查问题时对照着看。

网络抓包基础核心知识体系 网络抓包基础核心知识体系 抓包工具 过滤器 TCP连接管理 Wireshark Tcpdump 抓包过滤器 显示过滤器 三次握手 四次挥手 图形化界面 快捷键操作 统计分析 命令行工具 -w 保存文件 -c 限制数量 BPF语法 事前过滤 节省资源 Wireshark语法 事后过滤 灵活组合 SYN → SYN+ACK → ACK 确认双方收发能力 序列号同步 FIN → ACK → FIN → ACK 全双工独立关闭 2MSL等待 核心排查思路 选对工具 → 设置过滤器 → 抓包 → 分析TCP连接状态 → 定位性能瓶颈

这张图把本章内容分成了三个核心模块:抓包工具、过滤器和 TCP 连接管理。你在实际排查问题时,可以按这个思路走:先选对工具(Wireshark 还是 Tcpdump),然后设置合适的过滤器减少干扰,最后通过分析 TCP 连接状态来定位问题。

记住,抓包不是目的,目的是通过抓包看到网络通信的「真相」。很多性能问题,比如延迟高、丢包、连接重置,在抓包文件里都一目了然。多动手抓几次,你就能慢慢找到感觉了。