在Linux中抓取TCP三次握手需用tcpdump或tshark过滤SYN/SYN-ACK/ACK包,指定正确网卡(如eth0或lo),使用tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn等过滤条件,并验证三包IP端口成对、标志位符合SYN→SYN-ACK→ACK顺序。

在 Linux 中抓取 TCP 三次握手过程的数据包,核心是使用 tcpdump 或 Wireshark(tshark) 过滤出特定的 TCP 标志位(SYN、SYN-ACK、ACK),并确保捕获到完整的三次交互。关键在于理解握手特征、选择合适网卡、设置正确过滤条件。
确认目标连接和网络接口
三次握手发生在客户端与服务端之间,需先明确:
- 你要观察哪一对 IP 和端口(例如:192.168.1.100:54321 ↔ 192.168.1.200:80)
- 该连接走的是哪个网卡(用
ip a或ifconfig查,如eth0、lo、wlan0) - 若测试本地服务(如 curl 访问本机 nginx),注意 loopback(
lo)接口需显式指定,否则 tcpdump 默认不抓回环流量
用 tcpdump 抓取三次握手数据包
运行以下命令(替换 eth0 为实际接口名):
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn' -c 3
说明:
-
-i eth0:监听指定网卡 -
-nn:不解析主机名和端口名,避免 DNS 查询延迟,显示原始 IP 和端口号 -
tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn:匹配 SYN 包(含纯 SYN 和 SYN-ACK),这是三次握手中前两个包的共同特征 -
-c 3:只抓 3 个包,刚好覆盖 SYN → SYN-ACK → ACK(注意:第三个 ACK 可能不满足上述过滤条件,所以更稳妥的做法是抓更多再筛选)
更通用推荐写法(抓全三次握手):
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0 or tcp[tcpflags] & tcp-ack != 0 and (tcp[tcpflags] & tcp-syn == 0)' -w handshake.pcap
然后用 Wireshark 打开 handshake.pcap,按 tcp.flags.syn == 1 || tcp.flags.ack == 1 && tcp.flags.syn == 0 过滤,再结合时间戳和 IP:Port 组合识别完整三次握手。
用 tshark 快速提取三次握手流程
如果已安装 Wireshark 套件,可用 tshark 直接输出关键字段:
sudo tshark -i eth0 -nn -Y 'tcp.flags.syn == 1 or (tcp.flags.ack == 1 and tcp.flags.syn == 0)' -T fields -e frame.number -e ip.src -e ip.dst -e tcp.srcport -e tcp.dstport -e tcp.flags.syn -e tcp.flags.ack -o tcp.relative_sequence_numbers:FALSE | head -n 10
输出示例:
100 192.168.1.100 192.168.1.200 54321 80 1 0 ← SYN101 192.168.1.200 192.168.1.100 80 54321 1 1 ← SYN-ACK
102 192.168.1.100 192.168.1.200 54321 80 0 1 ← ACK
验证是否抓全及常见问题
抓包后检查三次握手是否完整,重点关注:
- 三个包的源/目的 IP 和端口是否成对出现(前后方向相反)
- 第一个包:SYN=1, ACK=0
- 第二个包:SYN=1, ACK=1
- 第三个包:SYN=0, ACK=1
- 若只看到 SYN 和 SYN-ACK,没看到 ACK,可能是连接未真正建立(如服务未响应)、防火墙拦截或抓包位置不对(如在服务端网卡却抓客户端发来的 ACK)
- 在容器或 Docker 环境中,可能需监听
docker0或cni0,而非物理网卡











