lwbaptx

HTTP协议的一次抓包分析

由于平时都是用印象笔记来做一些记录,所以很少写博客,这是之前的一次抓包分析http的过程,有空整理一下。

HTTP 是基于 TCP/IP 协议的应用层协议。它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。

rfc2616文档的介绍https://tools.ietf.org/html/rfc2616

HTTP请求格式

1
2
3
4
5
6
Request = Request-Line
*(( general-header | request-header | entity-header ) CRLF)
CRLF
[ message-body ]
Request-Line = Method SP Request-URI SP HTTP-Version CRLF
message-body = entity-body | <entity-body encoded as per Transfer-Encoding>

注:HTTP的换行CRLF是指”\r\n”(0x0d和0x0a),SP指的是空格0x20

比如通过fiddler捕获的下面的这个例子

1
2
3
4
5
6
7
8
9
GET http://192.168.50.224/show2.php HTTP/1.1
Host: 192.168.50.224
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,zh-TW;q=0.6

HTTP应答格式

1
2
3
4
5
Response = Status-Line
*(( general-header | response-header | entity-header ) CRLF)
CRLF
[ message-body ]
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

比如通过fiddler捕获的下面的这个例子

1
2
3
4
5
6
7
8
9
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Fri, 12 Jan 2018 06:18:37 GMT
Content-Type: text/html
Connection: keep-alive
Keep-Alive: timeout=5
X-Powered-By: PHP/5.5.9-1ubuntu4.17
Content-Length: 29
{"data":[],"probability":100}

下面是一张十六进制的数据图片
注意请求消息后面即使没有body,也会有一个空的\r\n行
这里的回复消息是根据Content-Length里面的29来读取body的长度的。

HTTP/1.1的分块传输编码

1:HTTP分块传输编码允许服务器为动态生成的内容维持HTTP持久链接。通常,持久链接需要服务器在开始发送消息体前发送Content-Length消息头字段,但是对于动态生成的内容来说,在内容创建完之前是不可知的。
2:分块传输编码允许服务器在最后发送消息头字段。对于那些头字段值在内容被生成之前无法知道的情形非常重要,例如消息的内容要使用散列进行签名,散列的结果通过HTTP消息头字段进行传输。没有分块传输编码时,服务器必须缓冲内容直到完成后计算头字段的值并在发送内容前发送这些头字段的值。
3:HTTP服务器有时使用压缩 (gzip或deflate)以缩短传输花费的时间。分块传输编码可以用来分隔压缩对象的多个部分。在这种情况下,块不是分别压缩的,而是整个负载进行压缩,压缩的输出使用本文描述的方案进行分块传输。在压缩的情形中,分块编码有利于一边进行压缩一边发送数据,而不是先完成压缩过程以得知压缩后数据的大小。

格式
https://tools.ietf.org/html/rfc2616#section-3.6.1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Chunked-Body   = *chunk
last-chunk
trailer
CRLF

chunk = chunk-size [ chunk-extension ] CRLF
chunk-data CRLF
chunk-size = 1*HEX
last-chunk = 1*("0") [ chunk-extension ] CRLF

chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)
trailer = *(entity-header CRLF)

如下图,在分块里面
82是130的十六进制的字符串表示,字符8的十六进制是0x38,字符2的十六进制是0x32
0是0的十六进制的字符表示,字符0的十六进制表示是0x30