以前抓 HTTP,右键 → Follow → TCP Stream,请求响应整整齐齐排好,一眼看完。
现在同样的操作,屏幕上是一堆交错的方块,一会儿是 HEADERS,一会儿是 DATA,Stream ID 跳来跳去。想看某个接口的响应,得在一坨数据里找。
不是 Wireshark 变难用了,是 HTTP 变了。这篇文章讲清楚变了什么,以及在新协议下该怎么抓。
HTTP/2 到底改了什么
一句话:一条 TCP 连接上跑很多条并行的流。
HTTP/1.1 的做法是一条连接一次一个请求,浏览器开六条连接凑并行。HTTP/2 把所有请求压进同一条 TCP,每条流有个编号(Stream ID),帧头里带着这个号,接收方按号拼回各自的请求。
好处是省连接、省握手、头部压缩(HPACK)。坏处是——对抓包的人——数据在物理上就是交织的:
Stream 1 HEADERS
Stream 3 HEADERS
Stream 1 DATA
Stream 5 HEADERS
Stream 3 DATA
Stream 1 DATA (END_STREAM)
Follow TCP Stream 是按字节顺序拼的,它不知道哪几个字节属于哪条流,所以给你看到的就是上面这种交错的样子。原始数据没错,只是没有语义。
先解决”看不到”的问题
打开抓包文件,如果只有 TLS Application Data,说明没解密,后面全都不用谈。
浏览器的话,设 SSLKEYLOGFILE 环境变量再启动,然后把 Wireshark 的 TLS 首选项指向那个文件。具体步骤上一篇 Wireshark 入门里写了,这里不重复。
解密成功后,协议列会从 TLS 变成 HTTP2,同时在 Info 里能看到 HEADERS[1]、DATA[1] 这样的标注。
还有一个前提容易被忽略:必须走 TLS 且 ALPN 协商成 h2。现在几乎所有网站都是这样,但如果你抓的是内网某个老服务,它可能还在跑 HTTP/1.1,那就还是老样子。看 TLS 握手里的 ALPN 字段,能确认协商的是什么。
纯明文的 h2c(不带 TLS 的 HTTP/2)理论上存在,实际极少,遇到了 Wireshark 需要手动指定「Decode As → HTTP2」。
三个过滤器,让 h2 变得可读
http2.streamid == 3
只看 3 号流。这是最实用的一个——先在概览里找到目标请求的 Stream ID,然后锁定它,世界立刻清净。
http2.headers
只看头部帧,跳过 DATA。想看接口路径和状态码的时候用这个。
http2.header.name contains "content-type"
按头部名过滤。查某个字段(比如 set-cookie)什么时候出现,比人工翻快得多。
想一次性把某条流的请求头导出来:
tshark -r cap.pcapng -Y "http2.streamid==3 && http2.headers" \
-T fields -e http2.header.name -e http2.header.value
输出是每行一个头,直接能粘到表格里对比。
新版有个 Follow HTTP/2 Stream
Wireshark 近几年的版本里,右键菜单多了一项 Follow → HTTP/2 Stream,能把单条流的数据拼出来。找到它之后,h2 的体验就接近以前了。
但它和 TCP Stream 有个同样的坑:中文默认按 Latin-1 显示。右下角切 UTF-8。
如果没有这一项,说明版本太老,升级比折腾过滤器划算。
HTTP/3 换了传输层
HTTP/3 不在 TCP 上跑了,它跑在 QUIC 上,QUIC 跑在 UDP 443。
这个变化带来的第一个后果很直接:所有基于 TCP 的分析手段全部失效。没有三次握手,没有 Follow TCP Stream,tcpdump 的 tcp port 443 一条都抓不到。
抓包过滤要改成:
udp port 443
就这一条。但抓下来之后,如果没解密,你看到的是 QUIC 的加密载荷,INFO 里只有包类型(Initial、Handshake、1-RTT),没有内容。
QUIC 把 TLS 1.3 内置了,所以解密同样需要密钥日志。好消息是 Wireshark 的 TLS 首选项里那个 keylog 文件对 QUIC 也生效,配一次两边都能解。
解密后协议列显示 HTTP3,能看到 HEADERS 和 DATA 帧,过滤用:
http3.headers
http3.streamid == 0
三个”为什么我抓不到 HTTP/3″
一、网站根本没启用。HTTP/3 需要考虑 UDP 被中间设备拦掉的情况,很多站点只对部分用户开,或者干脆没开。判断方法:看响应头有没有 alt-svc: h3=":443"。没有就是没开。
二、浏览器回退了。Chrome 会先试着用 QUIC,失败就退回 TCP。如果网络环境里 UDP 443 被封(公司网络很常见),你只会看到 h2 的流量,而且是”看起来正常”的那种。
三、Wireshark 版本太老。QUIC 的草案改过很多次,老版本可能把包识别成 UDP 或者解错。这类问题只能升级解决。
一个不依赖解密的办法
如果你只是想知道”这个页面到底发了多少个请求、各自耗时多少”,根本不需要抓包。
Chrome 打开 chrome://net-export/,开始记录,复现问题,停止,得到一个 JSON。再用 netlog-viewer 打开,能看到每条请求用的协议(h2 还是 h3)、连接复用情况、每个阶段的耗时。
这个方法的优势是:不用解密、不用配密钥、不受加密影响。缺点是看不到原始字节,只能看事件。
我一般的顺序是:先 net-export 看宏观(哪个请求慢、走的什么协议),再决定要不要抓包看细节。反过来做,经常抓了一堆包才发现问题根本不在网络上。
什么时候该用哪个
想知道”发了什么” —— 抓包 + 解密。h2 用 streamid 锁定,h3 用 http3.streamid。
想知道”慢在哪” —— 先 net-export,再决定。很多”网络慢”其实是服务端 TTFB 慢,抓包只能看到等待,看不到原因。
想验证”服务端有没有开 h3″ —— 一条 curl -I --http3 https://目标,看响应头。比自己抓省事。
最后
协议在变,工具在跟。HTTP/2 让”按字节顺序看”这个直觉失效,HTTP/3 干脆把传输层换了。
但底层逻辑没变:先确定流量走在哪条链路上、有没有加密、能不能解密。这三件事没搞清楚,换什么工具都是白抓。
顺带说一句,h2 的多路复用对排查也有好处:所有请求挤在一条连接上,你不用在六条连接里找对应关系了。前提是你得会按 streamid 过滤。
抓包分析仅限自有服务与授权范围。解密他人 HTTPS 流量,即使技术上可行,也属于违法行为。
- 1、本网站名称: 星宇安全实验室
- 2、本站永久网址:https://bk.zhaozhiqiang.pw/
- 3、本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
- 4、本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
- 5、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
- 6、本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。
- 7、文章版权归作者所有,未经允许请勿转载。















暂无评论内容