HTTP2协议解析及抓包分析

一、HTTP2协议简介

1、HTTP2的帧格式

HTTP2的所有帧都是由一个固定的9字节头部(payload之前)和一个指定长度的负载(payload)组成,如下图所示:

其中,Stream Identifier用作流控制,用31位无符号整数表示。客户端建立的sid必须为奇数,服务端建立的sid必须为偶数,值(0x0)保留给与整个连接相关联的帧(连接控制消息),而不是单个流。

Frame Payload是主体内容,有帧类型决定,HTTP2一共有10种类型的帧:

1
2
3
4
5
6
7
8
9
10
11
   名称           描述         type值
HEADERS 报头帧 0x1
DATA 数据帧 0x0
PRIORITY 优先级帧 0x2
RST_STREAM 流终止帧 0x3
SETTINGS 设置帧 0x4
PUSH_PROMISE 推送帧 0x5
PING PING帧 0x6
GOAWAY GOAWAY帧 0x7
WINDOW_UPDATE 窗口更新帧 0x8
CONTINUATION 延续帧 0x9

实际上,HTTP2并没有改变HTTP1.x的语义,只是把原来HTTP1.x的HeaderBody部分用Frame重新封装了一层而已。调试的时候浏览器设置会把HTTP2Frame自动还原成HTTP1.x的格式。两者的帧格式对比如下图:

2、HTTP2的改进及优点
  • 二进制分帧

    帧是客户端和服务端之间通信的最小单位,比起HTTP1.x这样的文本协议,二进制协议解析起来更高效,且没有冗余字段(HTTP1.x 协议每个包都会有重复传输的头部字段),占用带宽少。

  • 多路复用

    可以并行交错地发送请求,请求之间互不影响;

    可以并行交错地发送响应,响应之间互不干扰;

    只使用一个连接即可并行发送多个请求和响应;

    消除不必要的延迟,从而减少页面加载的时间;

增加了请求优先级字段,服务器可以根据流的优先级,控制资源分配,而在响应数据准备好之后,将优先级最高的帧发送给客户端。

增加了Header压缩,通信双方各自 cache 一份 header fields表。

增加了服务器推送,服务器可以对一个客户端请求发送多个响应,服务器向客户端推送资源无需客户端明确地请求。服务器推送通过PUSH那些它认为客户端将会需要的内容到客户端的缓存中,避免往返的延迟。比如,请求index.html,但服务器会把style.css, example.png等资源也发送给浏览器。

流量控制,每个HTTP2的流都拥有自己公示的流量窗口,它可以限制另一端发送数据。

二、配置Wireshark抓取HTTP2数据包

1、在电脑里创建一个后缀名为 .log 的文件,记住其路径。

2、在电脑的系统变量里创建一个新的变量,名为SSLKEYLOGFILE。配置了此变量后,浏览器会到这里来记录通信过程中密钥。

3、在wireshark中,分析 >> 已解析的协议...中,启用HTTP2的解析。并在 编辑 >> 首选项 >> Protocols >> TLS 中,配置 (Pre)-Master-Secret 为之前创建的log文件,之后,wireshark就可以凭借此文件中的秘钥解密HTTP2中的各个加密字段,便于我们进行协议分析。

三、HTTP2协议数据包解析

数据包点击下载

1、从上图可以看到,HTTP2协议的工作流程为:建立TCP连接、建立TLS连接、HTTP2通信,断开TCP连接 四个过程。在Client Hello中,客户端再扩展字段中会说明其所支持的协议,指定ALPN Next Protocolh2HTTP/1.1。之后,服务端在Server Hello中,回复所协商的接下来使用的应用层协议。如下图:

2、在TLS连接过程中,如果服务器支持session ticket,则发送New Session Ticket类型的握手报文,其中包含了能够恢复包括主密钥在内的会话信息。为了不让中间人可见,这个session ticket部分会进行编码、加密等操作,同时,还会指定此ticket的过期时间等。

3、从第一幅图中可以看出,在客户端发送Finished消息(#11)之后,就开始将HTTP封装到Application Data协议中发送给服务器(#12,#13,#14,#15,#16)了,此时,TLS握手还没有完全完成。

HTTP2中基本的协议单位是帧,每个帧都有不同的类型和用途。例如,报头(HEADERS)和数据(DATA)帧组成了基本的HTTP请求和响应;其他帧如设置(SETTINGS),窗口更新(WINDOW_UPDATE)和推送承诺(PUSH_PROMISE)是用来实现HTTP2的其他功能。

4、(#12)帧分析:在HTTP2请求创建连接发送SETTINGS帧初始化之前有一个Magic帧,为建立HTTP2请求的前言(connection preface),此前言作为对所使用协议的最终确认,并确定HTTP2连接的初始设置。在发送完前言后,双方都得向对方发送带有ACK标识的SETTINGS帧标识确认,对应图中的#21#22 号帧:

12号帧,组合了MagicSETTINGSWINDOW_UPDATE三种帧为一个数据包,其中包含的参数如下图:

WINDOW_UPDATE中的stream identifier0表示此窗口更新帧作用于整个连接,指定其他具体值可使其作用于某个特定的单独连接。

5、(#13)号帧分析,客户端在发送完连接前言后,可立即跟上一个请求(request)。这里客户端向服务器发送GET /HEADERSHEADERS帧用来打开一个流或携带一个首部块片段,此HEADERS帧包括了请求行和请求头的内容,属于1 号流:

其中,Exclusive:一个比特位声明流的依赖性是否是排它的,这里为 1,代表此流不依赖其他的流。Weight:代表当前流的优先级权重。End Headers:这里为 1 代表header块结束。Priority设置为 1,代表存在ExclusiveStream DependencyWeight

6、(#19) 号包分析,服务器向客户端发送SETTINGSWINDOW_UPDATE 帧,SETTINGS帧为连接前言 (connection preface),帧中设置了最大并行流数量、初始窗口大小、最大帧长度,WINDOW_UPDATE 给出扩大窗口的大小。这两个帧属于 0 号流。

7、DATA 帧,服务器向客户端发送DATA帧,即响应主体。DATA 帧用来装填主体信息,可以用一个或多个DATA 帧来返回一个请求的响应主体。

上图左边为HEADERS帧,服务器向客户端返回响应(response),此报头帧包含了状态行和响应头的内容,此帧属于 3 号流。 Status: 200 OK 表示状态码为 200,客户端请求成功。此外,响应头还给出了服务器所使用的的服务器型号、内容类型等。注意观察图中的标志位 End StreamEnd Headers 的变化。

-------------本文结束感谢您的阅读-------------
您的鼓励就是我创作的动力,求打赏买面包~~
0%