2. 分析TCP三次握手建立连接过程
任务目标
通过抓取TCP建立连接过程中的三个报文段(SYN、SYN-ACK、ACK),分析其TCP标志位、序号(SEQ)与确认号(ACK)的数值关系,并结合Wireshark的专家信息或状态统计,验证TCP三次握手的状态转换逻辑。
环境准备
- Wireshark 4.x(或3.6+)
- 本机回环接口(lo)或任意可用网卡
- Python 3.8+(仅用于启动本地TCP服务,便于抓包)
抓包步骤
- 启动Wireshark,选择回环接口(
lo)开始抓包。 - 在终端启动一个简单的TCP服务:
python3 -m http.server 8080。 - 另开终端执行:
curl http://127.0.0.1:8080/,随后立即停止Wireshark抓包。 - 在Wireshark过滤栏输入
tcp.port==8080,即可看到完整的握手报文。
关键代码:TCP三次握手状态验证脚本
以下Python脚本使用scapy库读取抓包文件(pcap/pcapng),自动提取三次握手的前三个TCP报文段,并输出标志位、序号、确认号及状态转换推断。若未安装scapy,先执行 pip install scapy。
from scapy.all import rdpcap, TCP, IP
def analyze_handshake(pcap_file):
packets = rdpcap(pcap_file)
handshake = []
for pkt in packets:
if TCP in pkt and pkt[TCP].dport == 8080 or (TCP in pkt and pkt[TCP].sport == 8080):
flags = pkt[TCP].flags
# 仅保留SYN、SYN-ACK、ACK(不含PSH等后续数据包)
if flags & 0x02 or (flags & 0x10 and not flags & 0x02):
handshake.append(pkt)
if len(handshake) == 3:
break
if len(handshake) < 3:
print("未捕获完整三次握手,请检查过滤条件")
return
# 报文1: SYN
p1 = handshake[0]
print(f"[1] {p1[IP].src}:{p1[TCP].sport} -> {p1[IP].dst}:{p1[TCP].dport}")
print(f" 标志位: SYN={bool(p1[TCP].flags & 0x02)}, ACK={bool(p1[TCP].flags & 0x10)}")
print(f" SEQ={p1[TCP].seq}, ACK_num={p1[TCP].ack}")
# 报文2: SYN-ACK
p2 = handshake[1]
print(f"[2] {p2[IP].src}:{p2[TCP].sport} -> {p2[IP].dst}:{p2[TCP].dport}")
print(f" 标志位: SYN={bool(p2[TCP].flags & 0x02)}, ACK={bool(p2[TCP].flags & 0x10)}")
print(f" SEQ={p2[TCP].seq}, ACK_num={p2[TCP].ack}")
# 报文3: ACK
p3 = handshake[2]
print(f"[3] {p3[IP].src}:{p3[TCP].sport} -> {p3[IP].dst}:{p3[TCP].dport}")
print(f" 标志位: SYN={bool(p3[TCP].flags & 0x02)}, ACK={bool(p3[TCP].flags & 0x10)}")
print(f" SEQ={p3[TCP].seq}, ACK_num={p3[TCP].ack}")
# 状态转换验证
print("\n--- 状态转换验证 ---")
print(f"客户端发送SYN后进入 SYN_SENT")
print(f"服务端收到SYN,回复SYN-ACK后进入 SYN_RCVD")
print(f"客户端收到SYN-ACK,发送ACK后进入 ESTABLISHED")
print(f"服务端收到ACK后也进入 ESTABLISHED")
if __name__ == "__main__":
import sys
if len(sys.argv) != 2:
print("用法: python3 analyze_handshake.py <抓包文件.pcap>")
else:
analyze_handshake(sys.argv[1])
运行与验证
- 将Wireshark保存的抓包文件(如
handshake.pcap)置于脚本同目录。 - 执行:
python3 analyze_handshake.py handshake.pcap - 观察输出,判定通过条件如下:
- 报文1:仅SYN=1,ACK=0,SEQ为客户端初始序号(记为x),ACK_num=0。
- 报文2:SYN=1且ACK=1,SEQ为服务端初始序号(记为y),ACK_num=x+1。
- 报文3:SYN=0,ACK=1,SEQ=x+1,ACK_num=y+1。
若输出满足上述数值关系,则说明三次握手标志位与序号确认号逻辑正确,状态转换过程与TCP协议规范一致。
常见问题
- 抓不到包:确认使用回环接口,且curl命令在抓包启动后执行。
- 脚本输出不足3个报文:过滤条件可能混入了HTTP请求数据包,可手动在Wireshark中右键第一个SYN包,选择“追踪TCP流”,确认流的前三个报文即为握手包。
- SEQ不是从0开始:现代操作系统启用随机初始序号(ISN),属正常现象,只需验证相对值(如ACK_num = SEQ+1)即可。