1. 为什么每个网络从业者都该亲手抓一次TCP包刚入行那会儿我对TCP的理解基本停留在三次握手、四次挥手这八个字上。面试能背考试能写但真到了线上环境一个接口偶发超时、一个文件传输速度上不去我盯着日志完全看不出门道。后来一位带我的前辈丢给我一句话你把Wireshark打开抓一次完整的TCP会话从头到尾看一遍比你看十篇文章都管用。这句话我记到现在。TCP抓包这件事看起来只是打开软件点个开始但它真正训练的是你对网络行为的直觉。数据包不会说谎重传就是重传乱序就是乱序窗口收缩就是窗口收缩所有应用层表现出来的卡慢断在传输层都有对应的证据。学会用Wireshark读这些证据你排查问题的效率会有质的飞跃。这篇内容面向的是刚接触网络分析的朋友也适合那些平时做后端开发、运维、测试但没系统做过抓包实验的人。我会从实验环境怎么搭、抓包点怎么选、过滤器怎么写一路讲到三次握手、四次挥手、重传、窗口这些核心机制在Wireshark里长什么样最后再分享几个我踩过的坑和实战排查思路。全程用真实可复现的操作来讲你跟着做一遍基本就能独立完成一次像样的TCP抓包分析。需要先说明一点抓包实验最好在自己完全可控的环境里做比如本机回环、虚拟机之间的通信或者你自己搭的测试服务。不要对着生产环境或者别人的网络随便抓这既是技术规范也是基本的职业素养。2. 实验环境搭建与抓包点的选择逻辑2.1 三种典型实验拓扑及各自适合观察什么做TCP抓包实验第一步不是打开Wireshark而是想清楚你要观察什么然后据此设计拓扑。我常用的有三种第一种是本机回环也就是访问127.0.0.1。这种拓扑最简单不需要第二台机器抓包直接在loopback接口上做。它适合观察TCP协议本身的握手挥手、窗口变化因为不经过物理网卡没有外部干扰包非常干净。缺点是看不到真实的网络延迟和丢包很多有趣的现象出不来。第二种是两台虚拟机互访用Host-Only或者内部网络连接。这种拓扑能模拟真实的端到端通信你可以人为制造延迟、丢包观察TCP的应对行为。我一般用这种做重传和拥塞控制的实验因为可控性强出问题也不影响外部。第三种是本机访问外部服务比如访问一个你自己部署在另一台测试机上的HTTP服务。这种最接近真实场景但变量多适合做综合性的分析练习。选哪种取决于你的实验目标。想看清协议细节选回环想观察异常行为选虚拟机互访想做端到端综合演练选第三种。2.2 抓包点决定了你能看到什么这是很多人忽略的关键点。Wireshark抓的是经过某个网卡的数据包你选的抓包点不同看到的视角完全不同。如果你在客户端抓包你看到的是我发出去了什么、我收到了什么。如果你在服务端抓包你看到的是我收到了什么、我回复了什么。如果中间还有一台机器做转发那又是另一个视角。同一个TCP会话在三个点抓到的包时间戳、顺序、甚至内容都可能不一样。我建议初学者先在客户端抓因为客户端视角最符合我请求了、对方响应了的直觉。等你熟练了再尝试同时在两端抓对比同一个包的发送时间和接收时间你就能直观理解网络延迟到底发生在哪一段。提示在虚拟机里抓包时要确认Wireshark绑定的是正确的虚拟网卡。很多人抓了半天没数据最后发现抓的是NAT网卡而流量走的是Host-Only网卡。2.3 Wireshark安装与权限那些事Wireshark在各平台的安装都很直接官网下载对应版本即可。但有两个细节值得说。一是权限问题。在Linux上普通用户默认没有抓包权限你需要把用户加入特定的用户组或者用管理员权限运行。Windows上则需要安装抓包驱动组件安装程序会提示你别跳过。macOS上首次运行会要求授权跟着提示走就行。二是网卡选择。Wireshark启动后会列出所有可用接口回环接口通常叫Loopback或者lo虚拟网卡名字里会带虚拟化平台的标识。选错了接口抓到的就是一片空白。我一般会先随便访问一个网页看哪个接口的流量在跳动就选哪个。安装完成后建议先做一个最小验证打开Wireshark选一个接口开始抓包然后在浏览器里访问一个页面看能不能抓到包。能抓到说明环境没问题可以进入正式实验了。3. 过滤器从海量数据包里捞出你要的那几条3.1 抓包过滤器和显示过滤器的本质区别这是新手最容易混淆的一对概念我必须先讲清楚。抓包过滤器是在抓取阶段生效的它决定哪些包被记录下来。一旦设了抓包过滤器不符合条件的包根本不会进入Wireshark的缓冲区。它的语法是BPF语法写起来相对严格。显示过滤器是在抓完之后生效的它只是把已经抓到的包做筛选展示原始数据还在。它的语法是Wireshark自己的语法灵活得多。我的习惯是抓包阶段尽量少过滤甚至不过滤先把数据都留下来分析阶段再用显示过滤器精确定位。因为抓包过滤器一旦设错该抓的包没抓到你就得重来一遍。而显示过滤器随时可以改不影响原始数据。3.2 最常用的显示过滤器写法下面这些是我日常用得最多的直接抄就行过滤目标过滤器写法说明某个IP的所有流量ip.addr 192.168.1.100收发都包含某个IP作为源ip.src 192.168.1.100只看它发出的某个端口tcp.port 8080收发都包含某条TCP流tcp.stream eq 0最精准推荐只看握手包tcp.flags.syn 1含SYN和SYN-ACK只看重传tcp.analysis.retransmission排查丢包神器只看复位tcp.flags.reset 1连接被强制断开排除某IPip.addr ! 192.168.1.100反向筛选其中tcp.stream eq N是我最推荐的。Wireshark会自动给每条TCP连接分配一个流编号你右键任意一个包选Follow TCP Stream它就会自动帮你过滤出这条连接的所有包。这个功能极大提升了分析效率尤其是当你在一个繁忙的接口上抓了几万个包的时候。3.3 抓包过滤器的几个实用例子如果你确实需要在抓包阶段就过滤下面几个BPF写法很实用# 只抓某个主机的流量 host 192.168.1.100 # 只抓某个端口 port 8080 # 只抓TCP且排除某个端口 tcp and not port 22 # 只抓两个主机之间的流量 host 192.168.1.100 and host 192.168.1.200注意抓包过滤器写错不会报错只会静默地抓不到东西。所以设完过滤器后先制造一点流量验证一下确认能抓到再开始正式实验。4. 三次握手在Wireshark里到底长什么样4.1 逐包拆解握手过程这是整个实验的核心部分。我以一个访问本机HTTP服务的会话为例带你逐包看。第一个包客户端发SYN。在Wireshark的协议树里展开TCP层你会看到几个关键字段源端口是客户端随机选的一个高位端口目的端口是服务端口Flags里SYN被置1Sequence number是一个随机初始值我们叫它Seqx。这个包的含义是我想跟你建立连接我的起始序号是x。第二个包服务端回SYN-ACK。它的Flags里SYN和ACK同时置1Acknowledgment number是x1意思是我收到了你的SYN期待你下一个字节是x1。同时它自己也带一个随机初始序号Seqy。这个包的含义是我同意建立连接我的起始序号是y同时确认收到你的了。第三个包客户端回ACK。Flags里只有ACK置1Acknowledgment number是y1Sequence number是x1。含义是我确认收到你的SYN了连接建立完成。三个包走完连接就建立了。你在Wireshark里会看到这三条记录颜色通常有区分时间戳间隔极小本机回环基本是微秒级。4.2 为什么初始序号是随机的这个问题很多人没想过。如果初始序号固定攻击者就能轻易伪造包、猜测后续序号从而劫持连接。随机化初始序号是为了让序列号不可预测这是TCP安全性的基础之一。在Wireshark里你能看到每次新建连接的初始序号都不一样而且数值很大通常是几十亿的范围。这不是随便选的而是基于时间和一个随机因子计算出来的保证在同一个连接的生命周期内不会回绕。4.3 握手中的异常信号正常的握手三个包干净利落。如果你看到下面这些情况就要警惕了SYN发出后没有SYN-ACK回应可能是服务没启动、端口没监听或者被中间设备拦截了。Wireshark里会看到客户端反复重传SYN。收到RST而不是SYN-ACK说明服务端明确拒绝了这个连接通常是端口没开。SYN-ACK的Acknowledgment number不对理论上应该是客户端Seq1如果对不上可能是中间有设备篡改或者抓包点位置导致看到了不完整的流。我遇到过一次很典型的情况客户端一直重传SYN服务端完全没反应。最后排查发现是服务端所在主机的防火墙把SYN丢了服务本身是正常的。这种问题如果只看应用日志你只会看到连接超时根本不知道卡在哪一步。抓包一看问题立刻定位。5. 四次挥手与连接状态的真实观测5.1 挥手为什么是四次而不是三次握手三次挥手四次这个不对称经常被问到。原因在于TCP连接是全双工的两个方向的数据流是独立的。关闭一个方向需要单独发一个FIN对方单独回一个ACK。两个方向都关闭就是两次FIN加两次ACK共四个包。具体过程是主动关闭方发FIN表示我没数据要发了被动关闭方回ACK表示知道了此时被动关闭方可能还有数据要发等它发完了再发自己的FIN主动关闭方回ACK连接彻底关闭。在Wireshark里你会看到FIN包和普通的ACK包混在一起。如果被动关闭方没有数据要发它的ACK和FIN可能会合并成一个包看起来就像三次但本质逻辑还是四次。5.2 TIME_WAIT状态在抓包里的体现主动关闭方发完最后一个ACK后不会立刻释放连接而是进入TIME_WAIT状态等待2MSL报文最大生存时间的两倍才真正关闭。这个状态在抓包里看不到直接的包但你能通过端口复用的行为间接观察到。为什么要等两个原因。一是保证最后一个ACK能到达对方如果对方没收到会重传FIN此时主动方还能响应。二是让本次连接的所有旧包在网络中消散避免它们干扰后续使用相同四元组的新连接。这个机制在高并发短连接场景下会带来问题大量TIME_WAIT状态占用端口资源。如果你在抓包里看到服务端有大量连接处于这个状态同时客户端报无法分配端口那基本就是这个问题。解决办法通常是启用端口复用或者改用长连接。5.3 异常关闭RST包的出现意味着什么正常关闭走FIN流程异常关闭则是RST。RST包一出现连接立刻终止不经过任何协商。常见的RST场景有连接一个没监听的端口服务端直接回RST应用程序崩溃操作系统代为发送RST中间设备因为策略原因强制中断连接。在Wireshark里RST包的Flags字段里Reset被置1颜色通常很醒目。看到RST你要做的第一件事是确认它是谁发的、在什么时机发的。如果是服务端在收到请求后立刻发RST多半是应用层处理出了问题如果是连接空闲很久后突然RST可能是中间设备的空闲超时策略。6. 重传、乱序与窗口TCP可靠传输的现场证据6.1 重传的三种类型及识别方法重传是TCP保证可靠性的核心手段但重传也分好几种Wireshark能帮你区分。超时重传发送方发了一个包等了超过RTO重传超时时间还没收到ACK就重发。在Wireshark里你会看到同一个Seq的包出现两次中间隔了一段明显较长的时间。Wireshark会标注Retransmission。快速重传接收方收到乱序包后会重复发送同一个ACK发送方连续收到三个重复ACK就立刻重传丢失的包不等超时。这种重传在抓包里表现为先有几个重复的ACK紧接着一个重传包。虚假重传有时候包其实到了只是ACK回来慢了发送方误以为丢了就重传。这种在抓包里表现为重传包和原包的ACK几乎同时到达。虚假重传会浪费带宽是网络质量不佳的信号。我一般用tcp.analysis.retransmission这个过滤器把所有重传捞出来然后逐个看时间间隔和上下文。如果重传率超过1%就说明网络质量有问题了。6.2 乱序和重复ACK的关联分析乱序是指包到达的顺序和发送顺序不一致。在Wireshark里你会看到Seq不是递增的某个较大的Seq先到了较小的Seq后到。乱序本身不一定是故障网络路径不同、负载均衡都可能造成乱序。但乱序会触发接收方发送重复ACK进而可能触发快速重传。所以你在抓包里经常看到乱序和重复ACK成对出现。分析乱序时重点看两点一是乱序的严重程度偶尔一两个包乱序问题不大大量乱序就要查网络二是乱序是否导致了不必要的重传如果重传的都是其实已经到达的包那就是虚假重传说明RTO设置可能偏激进。6.3 窗口字段告诉你对端还能收多少TCP的滑动窗口机制里每个ACK包都会带一个Window字段表示我还能接收多少字节。这个字段是流量控制的关键。在Wireshark里你可以把Window字段加为列直观看到窗口的变化。正常情况窗口应该保持在一个合理范围。如果你看到窗口逐渐缩小到接近零那就是零窗口现象说明接收方处理不过来发送方必须暂停发送。零窗口之后发送方会定期发窗口探测包询问接收方窗口是否恢复。这个过程在抓包里能看到一系列很小的探测包。如果窗口长时间不恢复应用层就会表现为卡住不动。窗口还有一个缩放因子的问题。TCP头部里的窗口字段只有16位最大65535但现代网络需要更大的窗口。所以握手时会协商一个窗口缩放因子实际窗口等于字段值乘以2的缩放因子次方。Wireshark会自动帮你算好实际值但你要知道这个机制的存在否则看到字段值很小却传输很快会感到困惑。7. 把抓包用到真实排查里几个我踩过的坑7.1 抓包点选错导致结论完全相反有一次排查一个服务端响应慢的问题我在客户端抓包看到从发请求到收响应隔了2秒就断定是服务端慢。后来在服务端也抓了一次发现服务端从收到请求到发出响应只用了50毫秒那2秒几乎全花在网络传输上。如果我只在客户端抓就会把锅甩错人。这件事教给我一个原则定位延迟问题一定要在两端都抓用时间戳做差。客户端发出的时间、服务端收到的时间、服务端发出的时间、客户端收到的时间四个时间点一对比延迟发生在哪一段一目了然。7.2 被TLS加密挡在门外怎么办现在大部分流量都是加密的抓到的包在应用层全是密文看不到HTTP内容。这时候你有几个选择。一是分析传输层。即使应用层加密TCP层的握手、重传、窗口、时序信息都是明文很多性能问题在传输层就能看出来。二是如果你有服务端的密钥可以配置Wireshark解密。这需要拿到会话密钥在受控的测试环境里是可行的。三是退而求其次用应用层日志配合抓包。抓包告诉你什么时候传了什么大小的数据日志告诉你这些数据是什么两者结合就能还原全貌。7.3 时间戳精度和时钟同步的坑Wireshark默认显示的是抓包主机的本地时间。如果你在多台机器上抓包做对比各机器的时钟没同步时间戳就对不上分析会完全错乱。我的做法是实验前先确保所有参与机器的时间同步。如果做不到就只在单点抓包分析或者用相对时间而不是绝对时间做对比。Wireshark里可以把时间显示改成相对于第一个包这样跨机器对比时至少能看相对间隔。另外抓包本身有时间戳精度问题。高精度场景下网卡硬件时间戳和软件时间戳差别很大。如果你的实验涉及微秒级分析要确认Wireshark用的是哪种时间戳源。7.4 大流量下Wireshark卡死的应对在繁忙接口上长时间抓包Wireshark很容易卡死或者丢包。几个应对办法用抓包过滤器减少数据量用命令行工具先抓成文件再用Wireshark离线分析增大缓冲区或者用环形缓冲区只保留最近的包。我个人的习惯是能用命令行抓就用命令行抓成pcap文件后再用Wireshark慢慢看。这样既不影响抓包主机性能分析时也更从容。8. 从实验到实战的能力迁移做完这一轮实验你应该对TCP的握手、挥手、重传、窗口有了直观认识。但实验环境和真实环境差别很大怎么把实验里学到的东西迁移到实战我的经验是抓住三个关键词基线、对比、证据。先建立基线。在系统正常的时候抓一次包记住正常的握手时间、重传率、窗口大小大概是什么范围。有了基线异常出现时你才能快速判断哪里不对。然后做对比。出问题时抓包和基线对比。是握手变慢了还是重传变多了还是窗口变小了差异点就是排查方向。最后用证据说话。不要凭感觉说网络慢要拿出抓包证据哪个包重传了、延迟多少毫秒、窗口收缩到多少。有了证据沟通效率会高很多也不会再出现互相甩锅的情况。还有一点很重要抓包只是手段不是目的。你要始终清楚自己在找什么。带着问题去抓包比漫无目的地抓一堆包然后不知道看什么效率高十倍。每次抓包前先问自己我要验证什么假设如果假设成立抓包里应该看到什么想清楚这两个问题再动手。最后分享一个我常用的练习方法找几个常见的网络场景比如大文件传输、短连接高频请求、弱网环境分别抓包分析把每种场景的特征记下来。积累多了你看到抓包文件就能大致判断出这是什么类型的流量、有没有异常。这种直觉是靠一次次实验喂出来的没有捷径。