Wireshark中TCP-TLS-HTTP2协议栈解析研究

解析原则

当程序面对一堆字节流,解析会严格按照协议约定的字段进行识别,按照报文中给出的长度切分字节流。
在OSI七层模型中,对于传输层以下的协议解析都比较简单,以链路层为以太网帧为例:

  1. 读取前14字节的以太网帧首部,从第13和14字节获取网络层协议类型,如IPv4
  2. 采用1.中获取的网络层协议格式,从第15字节开始按照IPv4的首部格式进行解析,根据协议字段获取到上层协议,如TCP,然后获取IPv4的首部长度并记录。
  3. 跳过2.中获取的IPv4首部长度,按照TCP的首部格式解析剩下的字节流,获取数据偏移字段,计算出TCP荷载的起始位置,即可获取到TCP传输的数据

然而在TCP首部中是没有专门字段标识上层协议的,而传输的数据可能会被层层被切分,需要另外的机制来实现TCP分组的重组,使之整合成TLS报文,同样的对于HTTP这种应用层报文,也有可能分在多个TLS报文中传输。

TLS报文识别和重组

由于TCP的首部没有专门标识上层协议的字段,当我们提取出TCP荷载时,面对一段一段的字节块,这些字节块实际上可以按照发送端TCP首部的seq_numlength组成一条字节流,通过计算seq_num + length得出的值就是下一个期望的seq_num,也就等于接收端的ack值。

但是这里还要注意一个不可忽视的问题,那就是TCP分组失序,网络层不能保证接收端按照时间轴依次接收到正确顺序的TCP包,而且丢包和重传机制同样也会导致TCP失序。一旦失序或者丢包发生,组成的字节流就不完整,进一步会影响到应用层协议的解析。这个问题我在试图使用Wireshark解密HTTPS时遇到过很多次,无奈的是Wireshark在处理TCP失序时不够给力,这个Bug在写本篇文章的时候依然没有修复,详细信息可以参考:https://gitlab.com/wireshark/wireshark/-/issues/15993

再回到TLS报文的识别问题上,假设根据TCP一段一段的荷载生成了一条完整的字节流,如图所示,TLS的头部以Content TypeVersion开始,对应的值为十进制的23和十六进制的0x0303,在下方可以看到是连续的0x170303,对于握手包来讲,Content Type的值会变成0x16,而TLS版本不同Version值也会不同,不过换来换去这种组合是有限的,可以根据这一点来识别TLS协议。

协议头部里面有一个字段为Length,这个值对于切分TLS报文有帮助,可以用来确定TLS荷载长度,当前已经组在一起的TCP荷载长度小于这个值时表明还需要下一段TCP荷载,而当前TCP荷载超过这个长度时表明需要在TCP荷载内部进行切分。

在这里插入图片描述

HTTP2报文识别和重组

HTTP2一般作为加密数据荷载被装进TLS报文中传输,只有在TLS被解密的情况下才能进一步识别和解析。同样的,在TLS报文首部也没有指示上层协议的字段,但是在TLS握手阶段会有一个应用层协议协商的过程,可以在握手包里看到协商使用了HTTP2协议,如下图所示:
在这里插入图片描述

另外HTTP2还有一种发现机制,在HTTP2开始连接的时候,客户端会发送一个Magic字节流,内容是PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n,通过这个特殊的包也可以确定可能使用了HTTP2协议(之所以说可能是因为HTTP2连接时有一个简单的协商过程,毕竟需要双端都支持h2而不是客户端一方说了算)。所以有的时候即使配置了Wireshark的解密密钥,还是无法显示出HTTP2包就有可能是Wireshark抓包错过了握手阶段,导致识别不出HTTP2协议。
当确定了HTTP2协议,就可以用HTTP2的协议格式进行解析,HTTP2的首部字段顺序为:Length,Type,Flag,Stream ID,Payload,通过读取Length字段即可截取或重组HTTP2报文。

解析例子

下图应该是一种比较复杂的情况(图片可以在新页面中打开看的更清晰),这里面的两个HTTP2报文(两个箭头所指)被分成了两个TLS(两个黄色框)传输,而这两个TLS又被分成了12个TCP分组片段。左上角的红色框表示当前的帧序号,第二个红色框表示了Wireshark将之前抓到的12个TCP包的字节块组合在一起,形成一条字节流。需要注意的是最后一个包#703,这里只取了前1203字节,而这个TCP包传输了1440字节,也就是说1204字节以后的数据可能是另外一个TLS首部的开头。下面的第二、三张图可以证明这个推测,第二张图是包#703TCP荷载的开头,从0x004a开始,向后移动1203字节,即图三中的0x04fd位置开头的0x170303,可知这是TLS1.2传输应用数据的报文首部开头。

所以这12个TCP包荷载拼成了两个TLS报文,进一步对TLS解密。如绿色框所示,再继续根据HTTP2首部中描述的长度,在第一个TLS荷载中提出第一个HTTP2完整报文,剩下的部分作为第二个HTTP2报文的前半部分。随后在第二个TLS荷载中提取出第二个HTTP2的后半部分,拼接成完整的HTTP2报文。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值