1. Wireshark入门:TCP协议抓包基础
第一次接触Wireshark时,我被密密麻麻的数据包列表吓到了。但当我真正理解TCP协议的工作原理后,这个工具立刻变成了排查网络问题的"X光机"。安装Wireshark非常简单,官网下载对应版本后一路下一步即可。启动后你会看到所有可用网卡的列表,选择正在使用的网卡(比如Wi-Fi或以太网)点击"Start"就开始抓包了。
新手最常遇到的困扰是抓包数据太多难以分析。这时候过滤器就是你的好帮手。比如要监控访问某网站的数据流,可以先用ping命令获取网站IP,然后在Wireshark过滤栏输入:
ip.addr == 180.101.49.12 and tcp.port == 443这个过滤条件会只显示与指定IP的443端口(HTTPS默认端口)的TCP通信。我建议新手从HTTP网站开始练习,因为HTTPS的加密数据会让你看不到实际内容。
2. 解密TCP三次握手全过程
2.1 第一次握手:SYN探路
当你在浏览器输入网址回车时,TCP连接的故事就开始了。第一个数据包永远是客户端发往服务器的SYN包。在Wireshark中,这个包的关键特征是:
- Flags字段只有SYN=1
- Sequence number是一个随机初始值(比如Seq=0)
- 没有Acknowledgment number
这时候客户端进入SYN_SENT状态,就像你敲门后等待主人应答。我遇到过SYN包发出后没响应的情况,通常是防火墙阻拦或网络不通。
2.2 第二次握手:SYN-ACK回应
服务器收到SYN后,会回复SYN+ACK包:
- Flags中SYN=1且ACK=1
- Acknowledgment number是客户端Seq+1(比如Ack=1)
- 服务器也会生成自己的Sequence number(比如Seq=0)
这个双重标志位说明服务器既确认了客户端的请求,也发起了自己的连接请求。此时服务器进入SYN_RCVD状态。
2.3 第三次握手:最终确认
客户端收到SYN-ACK后发送最后一个ACK:
- Flags中ACK=1
- Acknowledgment number是服务器Seq+1(比如Ack=1)
- Sequence number变为初始值+1(Seq=1)
三次握手完成后,连接进入ESTABLISHED状态。有趣的是,有些操作系统会把第三次握手的ACK包和后续的第一个数据请求包合并发送,这是TCP的延迟确认机制在起作用。
3. 深入TCP四次挥手过程
3.1 第一次挥手:FIN发起
当通信结束需要断开连接时,主动关闭方(可能是客户端或服务器)发送FIN包:
- Flags中FIN=1且ACK=1
- Sequence number是当前会话的累计值
- 发送方进入FIN_WAIT_1状态
我曾在生产环境遇到FIN包重传的问题,后来发现是因为对端处理关闭请求太慢导致的超时。
3.2 第二次挥手:ACK确认
被动关闭方收到FIN后,会立即回复ACK:
- Flags中ACK=1
- Acknowledgment number是收到的Seq+1
- 被动方进入CLOSE_WAIT状态
- 主动方收到后进入FIN_WAIT_2状态
这里有个关键点:CLOSE_WAIT状态表示等待应用层处理关闭。如果服务器出现大量CLOSE_WAIT,通常意味着应用程序没有正确关闭socket连接。
3.3 第三次挥手:被动方FIN
当被动关闭方完成数据处理后,会发送自己的FIN包:
- Flags中FIN=1且ACK=1
- Sequence number继续累计
- 被动方进入LAST_ACK状态
3.4 第四次挥手:最终确认
主动关闭方收到FIN后发送最后一个ACK:
- Flags中ACK=1
- Acknowledgment number是收到的Seq+1
- 主动方进入TIME_WAIT状态(等待2MSL时间)
- 被动方收到后立即关闭连接
TIME_WAIT状态经常让人困惑。它的存在有两个目的:确保最后一个ACK能到达对端,以及让网络中残留的旧报文段过期。在高并发服务器上,可以通过调整内核参数减少TIME_WAIT数量。
4. TCP状态异常分析与实战案例
4.1 CLOSE_WAIT堆积问题
这是我处理过最经典的TCP异常案例。某Java应用服务器出现大量CLOSE_WAIT连接,最终导致新连接无法建立。通过Wireshark抓包发现:
- 客户端正常发送FIN断开连接
- 服务器回复ACK但停留在CLOSE_WAIT
- 没有后续的FIN从服务器发出
根本原因是应用代码没有调用socket.close()。修复方法是确保所有网络资源都在finally块中释放。Linux下可以用这个命令查看CLOSE_WAIT数量:
netstat -ant | grep CLOSE_WAIT | wc -l4.2 SYN洪水攻击识别
某次运维值班时收到服务器连接数暴涨的报警。Wireshark抓包显示:
- 大量SYN包来自不同IP
- 服务器回复SYN-ACK但收不到第三次ACK
- 连接卡在SYN_RCVD状态
这是典型的SYN洪水攻击。临时解决方案是启用SYN Cookie,长期方案是配置防火墙规则限制SYN包速率。关键过滤条件:
tcp.flags.syn==1 and tcp.flags.ack==04.3 连接重置(RST)分析
RST包会立即终止连接。常见触发场景包括:
- 向已关闭的连接发送数据
- 端口未监听
- 报文校验错误
有次我们的应用频繁出现连接重置,抓包发现是客户端超时重传时服务端已经关闭了连接。解决方案是调整TCP的keepalive参数:
sysctl -w net.ipv4.tcp_keepalive_time=18005. Wireshark高级分析技巧
5.1 统计工具实战
Wireshark的统计功能非常强大:
- "Conversations"查看所有TCP会话
- "Flow Graph"生成连接时序图
- "IO Graph"分析流量波动
有次分析API性能问题时,我用IO Graph发现每5分钟就有流量尖峰,最终定位到是定时任务导致的。
5.2 重传分析
TCP重传是性能杀手。在Wireshark中:
- 使用过滤条件
tcp.analysis.retransmission - 查看"Expert Info"中的重传统计
- 分析RTT时间判断网络质量
我曾用这些方法发现了一个交换机端口错误配置导致的间歇性丢包问题。
5.3 高级过滤技巧
除了基础过滤,这些技巧很实用:
# 查找重传 tcp.analysis.retransmission # 查找零窗口(流量控制问题) tcp.window_size == 0 # 查找连接重置 tcp.flags.reset == 1 # 按流跟踪完整会话 tcp.stream eq 123记住,网络问题往往需要结合多个工具分析。我通常的排障组合是:Wireshark抓包 + tcpdump长期捕获 + netstat监控连接状态。