OpenVPN协议解析握手数据包分析.docx
- 文档编号:7110037
- 上传时间:2023-01-18
- 格式:DOCX
- 页数:10
- 大小:65.20KB
OpenVPN协议解析握手数据包分析.docx
《OpenVPN协议解析握手数据包分析.docx》由会员分享,可在线阅读,更多相关《OpenVPN协议解析握手数据包分析.docx(10页珍藏版)》请在冰豆网上搜索。
OpenVPN协议解析握手数据包分析协议解析握手数据包分析学习一种协议的最好的方式就是研究它的数据包,这样可以加深对协议的理解。
对于研究过某种协议数据包的家伙来讲,他一定知道协议头的哪个位置对应哪个字段,虽然这对于理解协议为什么这么设计可能没有太大的帮助,然而对于排查问题和实际实施是很有帮助的。
既然很多人都对RichardStevens的TCP/IP详解情有独钟,咱就剽窃他的风格,解析一下OpenVPN的握手是如何完成的。
本文分析70余个数据包,当然,最终我会略去重复的内容,来看看OpenVPN的握手协商过程。
1.分析前的解释1.1.数据包格式本文以如下格式分析每一个握手数据包,具体OpenVPN数据包的格式,请参阅OpenVPN协议解析-网络结构之外:
1.1.1.本文为了节省篇幅,省去了UDP以下各层的数据,直接从OpenVPN的封装开始。
1.1.2.以下为数据包格式,xx为十六进制字节:
A-B:
方向,分别为Server-Client和Client-Server|xx|:
操作码+keyid,1字节,xx右移5位就是操作码|xx|xx|xx|xx|xx|xx|xx|xx|:
sessionID,这个ID是单方向的,8字节|xx|xx|xx|xx|xx|xx|xx|xx|1a|de|38|06|ab|5e|55|0f|8f|ed|ea|ca|:
数据包消息MAC,本文启用tls-auth选项,本文MAC长度20字节(使用SHA1)|xx|xx|xx|xx|xx|xx|xx|xx|:
包id和时间戳,包括ack包的id和时间戳,在该方向每法送一个包,包id都会递增。
8字节|xx|.|xx|.:
如果ackbufferlength长度为0,没有ack信息,如果不为0,则后面包含确认的包序列号,然后追加一个对端的sessionid,变长|xx|xx|xx|xx|:
包序列号,不包括ack包,也就是说,发送一个非P_ACK包,包序列号才会递增,实际上如果是P_ACK包,根本就没有这一行字段。
4字节1.2.TLS/SSL握手协议关于TLS/SSL握手协议,最好的资料是RFC,然后或许看OpenSSL的源码上手更快些。
这里仅给出几个图示和几点解释,SSL握手协议包格式如下:
不管是记录协议还是握手协议,都会有一个recordheader,该record格式如下:
其中,如果是SSL握手协议的话,recordheader的type字段为0x16,我们使用的TLS,因此其major和minor分别为0x03和0x01。
接下来,我们看一下握手头:
其中握手类型分别为:
Clienthello:
0x01Serverhello:
0x02Certificate:
0x0bServerkeyexchange:
0x0cCertificaterequest:
0x0dServerhellodone:
0x0eCertificateverify:
0x0fClientkeyexchange:
0x10Finish:
0x141.3.SSL握手协议和OpenVPN握手的关系我们知道,OpenVPN的连接建立使用了SSL握手协议,可是却抓不到SSL握手包,实际上SSL握手协议是作为一种载荷封装在了OpenVPN的协议包里面了,SSL握手协议数据实际上是写入了一块内存,然后OpenVPN从该内存中读出这些数据包,然后封装后通过reliable层发出,数据到达对端后,解封装后写入一块内存,然后SSL从内存中读出SSL握手载荷,一切都是通过BIO实现的。
(如不甚理解,请参阅OpenVPN协议解析-网络结构之外)可以看出,SSL和OpenVPN属于不同的层次,SSL握手协议在OpenVPN握手协议之上,然而当SSL握手结束后,OpenVPN的密钥协议又在SSL记录协议协议之上,更清晰的图示如下所示:
因此,OpenVPN握手协议可以将SSL握手载荷随意拆分和合并,它们通过BIO建立的内存区域建立唯一的联系。
2.OpenVPN数据包详解2.1.第1个数据包Client-Server|38|5f|f2|07|b2|27|12|14|2d|5d|67|45|d5|59|1a|c5|b5|1a|de|38|06|ab|5e|55|0f|8f|ed|ea|ca|00|00|00|01|4d|da|14|7c|00|00|00|00|00|这是OpenVPN连接的第一个数据包,当然也是握手的第一个数据包,在这里首先要提出的是,通过紧接着后面两个数据包,我们可以看出,虽然OpenVPN首推UDP,且本文解析的数据包也是基于UDP的,然而对于OpenVPN握手,是必须要保持连接和保证传输的,因此实现了reliable层,OpenVPN的握手完全基于reliable层,等完成了握手,协商好了密钥(注意,这个密钥不是SSL握手协商出来的,而是在SSL记录协议上协商出来的),reliable层就不需要了,OpenVPN记录协议并不需要reliable层(它只是一个运输协议,如IP协议)。
既然reliable层是一个有连接和保证传输的协议层,那么最简便的实现方式就是模仿已有的实现,那就是TCP,虽然reliable层是一个高度简化的保证传输的版本,但是三次握手是少不了的,因此第一个数据包和下面两个数据包就是三次握手包。
除了和TCP一样,三次握手建立连接之外,OpenVPN的握手协议的三次握手还协商了一个信息,那就是密钥交换算法,这个协商通过其操作码可以看出,第一个数据包的操作码是0x38,右移5位就是7,因此其表示第二类密钥协商算法。
其中第二行表示一个session,这个session识别了一个连接,它是单方向的,每一个方向一个。
然后第三行是一个HMAC值,在本文,它是20个字节(特定于MD5和SHA1),这个HMAC只有在开启tls-auth时才存在,其计算的密钥是静态配置的,两端必须配置一致。
tls-auth相当于OpenVPN协议在已经很安全的SSL协议外又加固了一层,者有效防止了拒绝服务攻击,毕竟,SSL连接的安全性在于其建立安全通路的方式和建立后的安全性,其缺点就是消耗大量的资源。
再往下一行是一个packetid和一个时间戳,这两个字段一共占据8个字节,它有效的防止了重放攻击。
再往后一行,为一个单字节0x00,可见第一个数据包并不想确认任何数据,这也是正常的。
最后是一个包序列号,占据4个字节,为0,每个方向的非确认包(P_ACK),都拥有一个序列号,这个序列号是用于保证传输的,并不是用于防止重放攻击的,注意,它和packetid的意义是不同的,确认包并不包含序列号。
2.2.第2个数据包Server-Client|40|7a|26|7c|45|a6|72|e1|a2|b0|72|21|0a|c1|3f|f1|4a|bc|79|46|14|30|51|f3|0c|64|63|54|de|00|00|00|01|4d|da|14|7c|01|00|00|00|00|5f|f2|07|b2|27|12|14|2d|00|00|00|00|第二个数据包是服务器发往客户端的,类似于TCP的SYN/ACK,和第一个数据包一样,它的操作码也标识了密钥交换算法,这次是8,表示服务器使用第二类密钥交换算法,这样就和客户端达成了一致。
第二行是一个sessionid,这是另一方向的sessionid。
后面的数据意义和第一个包是一样的。
最后一行,也是一个4字节的0,这表示在从服务器端到客户端这个方向上,这是第一个数据包。
值得注意的是,我们看第5行,第一个字节为1,说明有一个数据包确认,紧接着4个字节为0,说明它确认的是Client到Server方向的第一个数据包,再往后的8个字节是Client到Server方向的sessionid。
2.3.第3个数据包Client-Server|28|5f|f2|07|b2|27|12|14|2d|40|20|5a|f4|92|2c|a7|4e|8e|f5|1a|e8|45|06|e7|5a|ae|64|64|85|00|00|00|02|4d|da|14|7c|01|00|00|00|00|7a|26|7c|45|a6|72|e1|a2|这是一个确认包,从操作码可以看出来,0x28右移5位就是5,这就是P_ACK_V1。
说明这是一个确认。
由于它是一个纯确认包,它没有最后的包序列号。
我们直接看第5行,它的意义和第二个数据包是一样的。
到此为止,实际上我们已经没有必要在继续分析下去了,如果你已经理解了这前三个数据包的话,实际上对于OpenVPN的握手协议你基本已经理解了。
然后我还要继续下去,因为接下来就要开始SSL握手了。
可以通过接下来OpenVPN的握手协议对SSL握手协议的封装来解释为何抓取不到OpenVPN的SSL连接握手包。
2.4.第4个数据包Client-Server|20|5f|f2|07|b2|27|12|14|2d|57|b8|8a|a1|3c|0f|84|2b|91|42|2a|92|c6|f4|55|c9|7c|82|48|65|00|00|00|03|4d|da|14|7c|00|00|00|00|01|16|03|01|00|5f|01|00|00|5b|03|01|4d|da|14|7c|77|15|6d|32|69|2a|3d|90|fc|8d|3d|a6|68|83|3f|11|e2|63|b7|1b|e5|d1|46|95|3b|99|a6|e5|00|00|34|00|39|00|38|00|35|00|16|00|13|00|0a|00|33|00|32|00|2f|00|66|00|05|00|04|00|63|00|62|00|61|00|15|00|12|00|09|00|65|00|64|00|60|00|14|00|11|00|08|00|06|00|03|01|00|通过前三个包的分析,我们看出,它们是没有包含数据的,这很类似于TCP的三次握手消息。
这第四个数据包是第一个包含数据的OpenVPN握手包。
如果我们仔细观察一下OpenVPN的握手协议头,发现它里面实际上是没有长度信息的。
这是因为我们讨论的是UDP上的OpenVPN,UDP数据报的长度是收发一致的,如果是TCP的话,它是流式的,收发不一致,当然是需要一个长度追加在操作码前面。
另外,在深入数据载荷之前,我们看一下第六行,也就是一个4个字节的包序列号,这时是0x01,说明这是Client到Server方向的第二个数据包,我们数一下,也真的是这样。
好了,我们看一下其数据载荷的前面几个字节,其前5个字节0x16,0x03,0x01,0x00,0x5f,我们发现它是SSL记录头的格式,0x16是其type,实际上就是握手协议,后面的0x03和0x01是major和minor号,后面的两个字节表示SSL握手消息长度,那么它到底是什么SSL握手消息呢?
我们根据SSL握手协议头的格式,其第一个字节是0x01,也就是Clienthello,它的长度是后面的3个字节。
最终,我们发现,这个OpenVPN协议封装的数据载荷就是SSL握手消息中的Clienthello消息。
2.5.第5个数据包Server-Client|20|7a|26|7c|45|a6|72|e1|a2|4c|b7|ae|78|e9|67|ca|bb|2b|71|0d|fc|48|51|08|9a|30|6c|dd|54|00|00|00|02|4d|da|14|7c|01|00|00|00|01|5f|f2|07|b2|27|12|14|2d|00|00|00|01|16|03|01|00|2a|02|00|00|26|03|01|4d|da|14|7c|5b|f3|9a|fa|b9|d3|b1|75|b7|ba|4f|9d|33|6e|4b|25|cc|f3|dd|6f|d6|73|b0|6e|f0|ac|aa|f4|00|00|39|00|16|03|01|04|8b|0b|00|04|87|00|04|84|00|02|41|30|82|02|3d|30|82|01|a6|02|09|00|fb|0e|c2|7f|49|2a|44|8b|30|0d|06|09|2a|86|48|86|f7|0d|01|01|05|05|00|30|61|31|0b|通过第四个数据包的分析,我们很简单的分析出这个OpenVPN协议封装的数据载荷是Serverhello消息,因为|16|03|01|00|2a|02|中02表示Serverhello。
如果仔细往下看,我们最终又发现了一个SSL记录头序列:
|16|03|01|04|8b|,紧接着的是|0b|00|04|87|,这明显又是一个SSL握手消息,0x0b是其消息类型,我们发现它是Certificate,它的长度是0x0487,这可够长的了.SSL握手消息之所有可以在OpenVPN协议封装的任意位置,是因为它只是数据载荷的一部分,再次重申,SSL协议被OpenVPN协议封装了,SSL是载荷,OpenVPN提供封装和运输服务,不管怎样拆分,最终总是能保证数据能可靠到达对端,由对端的SSL协议负责进行组合。
2.6.第6个数据包Server-Client|20|7a|26|7c|45|a6|72|e1|a2|16|28|bc|a4|3a|34|01|45|26|2b|ab|59|ea|ee|d3|88|b4|dd|11|ee|00|00|00|03|4d|da|14|7c|00|00|00|00|02|30|09|06|03|55|04|06|13|02|61|61|31|0b|30|09|06|03|55|04|08|13|02|61|61|31|0b|30|09|06|03|55|04|07|13|02|61|61|31|0b|30|09|06|03|55|04|0a|13|02|61|61|31|0b|30|09|06|03|55|04|0b|13|02|61|61|31|0b|30|09|06|03|55|04|03|13|02|63|61|31|11|30|0f|06|09|2a|86|48|86|f7|0d|01|09|01|16|02|61|61|30|1e|17|0d|31|这个数据包比较奇怪,因为我们没有在数据载荷的开始处发现任何SSL协议的识别标识,另外,如果我们仔细分析上一个数据包,也就是第五个数据包中在中间封装的Certificate消息,它的长度是0x0487,可是无论怎么看,第五个数据包整个也没有那么长,那么这么长的数据到底在哪里呢?
答案就是在后续的数据包中,这就类似IP分片,非头IP分片的载荷中,是没有包含传输层协议头的,也可以通过TCP分段来理解.OpenVPN的实现中,在reliable层中实现了根据虚拟网卡MTU或者当前网络状况任意拆分数据的功能,这样可达到高效利用网络的目的。
这样,即使一个1000字节的SSL握手消息,reliable层也可以将其拆成10个100多字节的UDP包,数据到达对端后,每一个100多字节的UDP包进入其SSLBIO的内存BIO中,由SSL协议的实现负责重组数据。
我们可以将reliable层当成一个在UDP上伪装的伪TCP,该伪TCP直接和SSL的内存BIO接口。
在了解了上述原理之后,我们直接略过Server传输的Certificate消息,当然还是会分析一个Client的确认包,因为reliable层是需要确认的,这就是接下来马上就要分析的第九个数据包。
2.7.第9个数据包Client-Server|28|5f|f2|07|b2|27|12|14|2d|60|e1|38|28|46|ef|63|5e|46|e6|31|9c|fd|7f|40|7d|df|bd|fd|df|00|00|00|04|4d|da|14|7c|01|00|00|00|01|7a|26|7c|45|a6|72|e1|a2|这是一个纯确认包,我们看到其操作码是5,它确认的是Server发送的Certificate的OpenVPN协议封装的一部分,当然这样的包有好几个,这里仅仅揪出一个来分析。
它确认的是Server发送的第两个数据包,也就是第五个数据包。
2.8.第27个数据包Server-Client|20|7a|26|7c|45|a6|72|e1|a2|0a|1d|15|d6|1a|42|e6|57|29|18|71|b9|db|fd|d1|43|9d|6d|ef|8a|00|00|00|0e|4d|da|14|7c|00|00|00|00|0d|69|67|1e|99|7a|a1|8b|9d|b1|e7|9a|bb|8b|ca|49|16|03|01|01|8d|0c|00|01|89|00|80|bf|88|f7|46|21|4c|81|5c|20|77|d5|5a|52|1b|d4|e8|94|90|e4|84|ae|74|1a|82|f9|c1|0d|f2|ac|ea|10|2f|25|12|41|d8|d2|41|64|44|a2|a1|42|3f|73|1a|79|0c|e1|d4|64|8e|35|a1|1b|00|90|9f|29|8b|bd|ae|16|84|45|d9|44|f9|44|00|d1|03|fa|3e|在这个OpenVPN协议封装的中间,我们发现了Server的Serverkeyexchange消息。
这个道理请参照2.6节。
2.9.第34个数据包Server-Client|20|7a|26|7c|45|a6|72|e1|a2|8c|6e|d5|13|e0|f8|14|13|c3|c6|d7|e3|b0|7f|7b|10|92|0c|85|b5|00|00|00|12|4d|da|14|7c|00|00|00|00|11|b5|e4|de|cb|85|b9|10|0c|1f|d6|7a|21|56|2c|7e|ca|15|16|03|01|00|74|0d|00|00|6c|04|03|04|01|02|00|65|00|63|30|61|31|0b|30|09|06|03|55|04|06|13|02|61|61|31|0b|30|09|06|03|55|04|08|13|02|61|61|31|0b|30|09|06|03|55|04|07|13|02|61|61|31|0b|30|09|06|03|55|04|0a|13|02|61|61|31|0b|30|09|06|03|55|04|0b|13|02|在这个OpenVPN协议封装的中间,我们发现了Server的Certificaterequest消息。
这个道理请参照2.6节。
2.10.第36个数据包Server-Client|20|7a|26|7c|45|a6|72|e1|a2|a4|af|b5|cd|45|2e|33|ea|ff|6b|0b|58|b2|fc|1b|41|bd|e4|ef|99|00|00|00|13|4d|da|14|7c|00|00|00|00|12|61|61|31|0b|30|09|06|03|55|04|03|13|02|63|61|31|11|30|0f|06|09|2a|86|48|86|f7|0d|01|09|01|16|02|61|61|0e|00|00|00|最终,在数据载荷的最后,我们发现了|0e|00|00|00|序列,这是什么呢?
我们知道,Serverhellodone的握手type是0x0e,其后三个字节为消息长度,为全0,这个消息只是想告诉Client,Server发送的消息结束了,Client可以发送数据了。
注意,和往常不一样,Serverhellodown消息并没有SSL记录头序列,而是直接贴在消息后面的。
我们只是想分析OpenVPN协议,而不是SSL协议,因此不会过分叙述SSL握手的细节。
接下来的OpenVPN协议封装的载荷包含了Client发送给Server的Certificate,Verify,Clientkeyexchange消息等,我们略过这部分重复且枯燥的叙述。
2.11.第65个数据包Client-Server|20|5f|f2|07|b2|27|12|14|2d|56|ae|02|5f|0c|22|95|78|b7|7e|fb|24|8e|f9|34|56|69|09|87|e7|00|00|00|23|4d|da|14|7c|00|00|00|00|10|0f|17|d5|75|85|7b|ba|84|e9|b2|a0|9b|22|cc|ad|cc|cf|aa|38|6d|1c|ef|2b|23|69|8f|06|ac|81|79|50|7c|00|cb|21|0d|26|7d|26|81|14|28|bd|45|36|02|14|03|01|00|01|01|16|03|01|00|30|fc|bf|67|e0|a3|95|5d|ee|e1|59|fb|16|2d|c0|7a|55|82|de|73|34|02|1c|a2|88|15|4a|92|c6|6e|41|87|e4|a1|94|e8|f8|e5|31|e1|e0|ae|2f|7d|注意,我们发现了|14|03|01|00|01|01|序列,这个序列特殊吗?
是的,很特殊,因为这并不属于SSL握手协议,而是一个单独的SSL协议,那就是CHANGE_CIPHER_SPEC协议,这个协议说明,SSL通道上的安全密钥(加密对称密钥,摘要密钥等)已经建立,接下来的消息将会被这些密钥作用,因此接下来的消息我们将无法再看到了,它们是加密的。
CHANGE_CIPHER_SPEC协议规定,其数据载荷就是一个0x01,因此其长度也就是1,故而出现了|14|03|01|00|01|01|序列。
我本来想把这个数据包作为一个终结,结束讨论,因为以后的数据包都是通过SSL握手协商出来的安全通道加密的,也就无法理解其中的内容了,这样分析还有什么意义呢?
我们知道,SSL握手的最后一步是Finish消息,这个消息是协议规定的,可是我们再也看不到了。
2.12.第71个数据包Server-Client|20|7a|26|7c|45|a6|72|e1|a2|c8|eb|b1|85|e7|b2|bb|34|f1|96|0e|00|1f|56|df|21|30|34|a3|0e|00|00|00|23|4d|da|14|7c|01|00|00|00|11|5f|f2|07|b2|27|12|14|2d|00|00|00|13|14|03|01|00|01|01|16|03|01|00|30|8f|57|7d|42|ae|a3|89|2d|34|5a|a7|d1|f7|08|ef|a1|bd|8b|52|1c|32|56|da|5d|33|0b|f2|95|82|d2|f3|c8|60|69|e6|0b|c2|0d|88|65|cf|fc|af|b4|93|6e|0c|31|无疑,这个数据包的载荷中也包含了|14|03|01|00|01|01|序列,这是Server发送的CHANGE_CIPHER_S
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- OpenVPN 协议 解析 握手 数据包 分析
![提示](https://static.bdocx.com/images/bang_tan.gif)