tcpdump与Wireshark抓包分析
约 2142 字大约 7 分钟
tcpdumpwireshark
2025-07-18
概述
网络抓包是排查网络问题的终极手段——当其他工具无法定位问题时,抓包分析能揭示网络通信的完整真相。tcpdump是命令行抓包工具,适合服务器环境;Wireshark是图形化分析工具,提供强大的协议解析和可视化能力。两者配合使用效果最佳。
tcpdump基础
BPF过滤语法
tcpdump使用BPF(Berkeley Packet Filter)语法进行包过滤。
# 基本过滤语法
# 按主机过滤
tcpdump host 10.0.0.1
tcpdump src host 10.0.0.1
tcpdump dst host 10.0.0.1
# 按网段过滤
tcpdump net 10.0.0.0/24
# 按端口过滤
tcpdump port 80
tcpdump src port 443
tcpdump portrange 8000-8100
# 按协议过滤
tcpdump tcp
tcpdump udp
tcpdump icmp
tcpdump arp
# 组合过滤(and/or/not)
tcpdump 'host 10.0.0.1 and port 80'
tcpdump 'src 10.0.0.1 and (dst port 80 or dst port 443)'
tcpdump 'not port 22'
tcpdump 'tcp and not port 22 and not port 53'
# 高级过滤(TCP标志位)
tcpdump 'tcp[tcpflags] & tcp-syn != 0' # SYN包
tcpdump 'tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn' # 仅SYN(不含SYN+ACK)
tcpdump 'tcp[tcpflags] & tcp-rst != 0' # RST包
tcpdump 'tcp[tcpflags] & tcp-fin != 0' # FIN包
# 按包大小过滤
tcpdump 'greater 1000' # 大于1000字节
tcpdump 'less 100' # 小于100字节
# 按VLAN
tcpdump 'vlan 100'常用抓包选项
# 关键选项
sudo tcpdump -i eth0 # 指定接口
sudo tcpdump -i any # 所有接口
sudo tcpdump -c 100 # 抓100个包后停止
sudo tcpdump -w output.pcap # 保存为pcap文件
sudo tcpdump -r input.pcap # 读取pcap文件
sudo tcpdump -nn # 不解析主机名和端口名
sudo tcpdump -tttt # 显示可读时间戳
sudo tcpdump -v/-vv/-vvv # 详细程度递增
sudo tcpdump -A # ASCII显示包内容
sudo tcpdump -X # 十六进制+ASCII显示
sudo tcpdump -s 0 # 抓取完整包(默认可能截断)
sudo tcpdump -S # 显示绝对序列号
# 文件轮转(长时间抓包)
sudo tcpdump -i eth0 -w capture_%Y%m%d_%H%M%S.pcap \
-G 3600 \ # 每3600秒(1小时)轮转
-C 100 \ # 每100MB轮转
-W 24 # 最多保留24个文件
# 生产环境抓包最佳实践
sudo tcpdump -i eth0 -nn -s 0 -w /tmp/debug.pcap \
'host 10.0.0.1 and port 8080' \
-c 10000 # 限制包数量,防止磁盘写满tcpdump输出解读
# 典型TCP输出
sudo tcpdump -i eth0 -nn port 80
# 输出示例:
# 15:42:01.123456 IP 10.0.0.1.54321 > 10.0.0.2.80: Flags [S], seq 1234567890, win 65535, options [mss 1460,sackOK,TS val 123456 ecr 0,nop,wscale 7], length 0
# 15:42:01.123789 IP 10.0.0.2.80 > 10.0.0.1.54321: Flags [S.], seq 987654321, ack 1234567891, win 65535, options [mss 1460,sackOK,TS val 789012 ecr 123456,nop,wscale 7], length 0
# 15:42:01.124012 IP 10.0.0.1.54321 > 10.0.0.2.80: Flags [.], ack 1, win 512, length 0
# Flags解读:
# [S] = SYN
# [S.] = SYN+ACK
# [.] = ACK
# [P.] = PSH+ACK(推送数据)
# [F.] = FIN+ACK
# [R] = RST
# [R.] = RST+ACKWireshark分析
显示过滤器(Display Filter)
Wireshark的显示过滤器语法与tcpdump的BPF不同,更加直观:
# 基本过滤
ip.addr == 10.0.0.1
ip.src == 10.0.0.1
ip.dst == 10.0.0.2
tcp.port == 80
tcp.srcport == 443
udp.port == 53
# 协议过滤
http
dns
tls
tcp
udp
arp
# HTTP过滤
http.request.method == "GET"
http.request.uri contains "/api/"
http.response.code == 200
http.response.code >= 400
http.host == "example.com"
http.content_type contains "json"
# TCP过滤
tcp.flags.syn == 1 and tcp.flags.ack == 0 # 仅SYN
tcp.flags.rst == 1 # RST包
tcp.analysis.retransmission # 重传
tcp.analysis.duplicate_ack # 重复ACK
tcp.analysis.zero_window # 零窗口
tcp.analysis.window_update # 窗口更新
tcp.stream == 5 # 特定TCP流
# TLS过滤
tls.handshake.type == 1 # ClientHello
tls.handshake.type == 2 # ServerHello
tls.handshake.extensions_server_name == "example.com" # SNI
# DNS过滤
dns.qry.name == "example.com"
dns.flags.response == 1 # 响应
dns.flags.rcode != 0 # 错误响应
# 组合过滤
ip.addr == 10.0.0.1 and tcp.port == 80
not arp and not dns
http or tls
(ip.src == 10.0.0.1 and ip.dst == 10.0.0.2) or icmpTCP流跟踪(Follow TCP Stream)
Follow TCP Stream示例输出:
GET /api/users HTTP/1.1 ← 红色(客户端)
Host: api.example.com
Accept: application/json
HTTP/1.1 200 OK ← 蓝色(服务端)
Content-Type: application/json
Content-Length: 256
{"users":[...]}常用Wireshark分析功能
1. IO Graph(IO图表)
Statistics → IO Graphs
- 可视化流量随时间的变化
- 添加多个过滤器对比
- 发现流量异常和突发
2. Expert Information(专家信息)
Analyze → Expert Information
- 自动检测网络异常
- 分类:Error/Warning/Note/Chat
- 重传、重复ACK、零窗口等
3. Conversations(会话统计)
Statistics → Conversations
- 查看所有通信对
- 按流量/包数/持续时间排序
- 快速定位大流量源
4. Protocol Hierarchy(协议层次)
Statistics → Protocol Hierarchy
- 统计各协议的流量占比
- 发现异常协议流量
5. Flow Graph(流程图)
Statistics → Flow Graph
- TCP流的时序图
- 可视化握手、数据传输、挥手协议分析实战
TCP三次握手分析
# tcpdump抓取握手过程
sudo tcpdump -i eth0 -nn -S 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0' and host 10.0.0.1
# Wireshark过滤
tcp.flags.syn == 1 or tcp.flags.fin == 1完整握手包分析:
No. Time Source Dest Info
1 0.000000 10.0.0.1:54321 10.0.0.2:80 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=128 SACK_PERM
2 0.001234 10.0.0.2:80 10.0.0.1:54321 [SYN,ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460 WS=128 SACK_PERM
3 0.001456 10.0.0.1:54321 10.0.0.2:80 [ACK] Seq=1 Ack=1 Win=65536 Len=0
关注点:
- MSS值(1460正常,更小可能有隧道封装)
- Window Scale(WS值影响最大窗口大小)
- SACK_PERM(支持选择性确认)
- 握手耗时(No.1到No.3的时间差)重传分析
# Wireshark过滤重传
tcp.analysis.retransmission or tcp.analysis.fast_retransmission
# tcpdump查看可能的重传(相同seq号)
sudo tcpdump -i eth0 -nn -S 'tcp and host 10.0.0.1 and port 80'TLS解密
Wireshark可以使用pre-master secret日志解密TLS流量:
# 方法1:设置环境变量让浏览器/curl输出密钥
export SSLKEYLOGFILE=/tmp/sslkeys.log
# 然后启动浏览器或curl
curl https://example.com
# 密钥会写入 /tmp/sslkeys.log
# Wireshark配置:
# Edit → Preferences → Protocols → TLS
# (Pre)-Master-Secret log filename: /tmp/sslkeys.log
# 方法2:使用服务器私钥(仅适用于RSA密钥交换,不适用于ECDHE)
# Edit → Preferences → Protocols → TLS → RSA keys list
# IP: 10.0.0.1, Port: 443, Protocol: http, Key File: server.key# sslkeys.log格式示例
CLIENT_RANDOM abc123...def456 master_secret_hex...
CLIENT_RANDOM 789abc...012def master_secret_hex...性能分析
TCP性能指标(Wireshark提取):
1. RTT(往返时延)
过滤: tcp.analysis.ack_rtt
Statistics → TCP Stream Graphs → Round Trip Time
2. 吞吐量
Statistics → TCP Stream Graphs → Throughput
3. 窗口大小
Statistics → TCP Stream Graphs → Window Scaling
零窗口: tcp.analysis.zero_window
4. 重传率
Statistics → Expert Information → 查看Retransmission数量
重传率 = 重传包数 / 总包数
5. 延迟分解
- DNS解析: dns.time
- TCP连接: tcp.analysis.initial_rtt
- TLS握手: 从ClientHello到Application Data
- 服务器处理: 从请求完成到响应开始高级tcpdump技巧
# 抓取HTTP请求方法
sudo tcpdump -i eth0 -A -s 0 'tcp dst port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' | grep -E "^(GET|POST|PUT|DELETE|HEAD)"
# 抓取DNS查询
sudo tcpdump -i eth0 -nn port 53 -l | grep -E "A\?|AAAA\?"
# 检测SYN Flood
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] == tcp-syn' -c 1000 | \
awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn | head
# 统计每秒包数(PPS)
sudo tcpdump -i eth0 -nn -q 2>/dev/null | \
awk -F. '{print $1}' | uniq -c
# 实时监控HTTP状态码
sudo tcpdump -i eth0 -A -s 0 'tcp src port 80' 2>/dev/null | \
grep -oE "HTTP/1\.[01] [0-9]{3}" | sort | uniq -c | sort -rn
# 抓取慢查询(响应时间 > 阈值)
# 用tshark(Wireshark命令行版本)
tshark -i eth0 -f "port 80" -T fields \
-e frame.time -e ip.src -e ip.dst \
-e http.request.uri -e http.time \
-Y "http.time > 1"tshark命令行分析
# tshark - Wireshark的命令行版本
# 读取pcap文件并过滤
tshark -r capture.pcap -Y "http.request"
# 提取特定字段
tshark -r capture.pcap -T fields \
-e frame.number -e frame.time_relative \
-e ip.src -e ip.dst \
-e tcp.srcport -e tcp.dstport \
-e http.request.uri \
-Y "http.request"
# 统计HTTP响应码
tshark -r capture.pcap -z http,stat, -q
# 统计会话
tshark -r capture.pcap -z conv,tcp -q
# 导出HTTP对象
tshark -r capture.pcap --export-objects http,/tmp/http_objects/
# 统计DNS查询
tshark -r capture.pcap -Y "dns.qry.name" -T fields -e dns.qry.name | \
sort | uniq -c | sort -rn | head -20抓包工作流
总结
tcpdump和Wireshark是网络故障排查的最有力工具。tcpdump擅长在服务器上实时抓包和初步过滤,Wireshark擅长深度分析和可视化。掌握BPF过滤语法和Wireshark显示过滤器是高效抓包的基础。在生产环境中抓包时,务必使用精确的过滤条件和包数量限制,避免对性能造成影响和磁盘空间耗尽。
贡献者
更新日志
2026/3/14 13:09
查看所有更新日志
9f6c2-feat: organize wiki content and refresh site setup于