OpenVPN协议解析-握手数据包分析

学习一种协议的最好的方式就是研究它的数据包,这样可以加深对协议的理解。对于研究过某种协议数据包的家伙来讲,他一定知道协议头的哪个位置对应哪个字段,虽然这对于理解协议为什么这么设计可能没有太大的帮助,然而对于排查问题和实际实施是很有帮助的。既然很多人都对Richard Stevens的《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|:操作码+key id,1字节,xx右移5位就是操作码
|xx|xx|xx|xx|xx|xx|xx|xx|:session ID,这个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|...]:如果ack buffer length长度为0,没有ack信息,如果不为0,则后面包含确认的包序列号,然后追加一个对端的session id,变长
|xx|xx|xx|xx|:包序列号,不包括ack包,也就是说,发送一个非P_ACK包,包序列号才会递增,实际上如果是P_ACK包,根本就没有这一行字段。4字节
1.2.TLS/SSL握手协议
关于TLS/SSL握手协议,最好的资料是RFC,然后或许看OpenSSL的源码上手更快些。这里仅给出几个图示和几点解释,SSL握手协议包格式如下:

落雪病毒专杀
不管是记录协议还是握手协议,都会有一个record header,该record格式如下:
索南加乐

其中,如果是SSL握手协议的话,record header的type字段为0x16,我们使用的TLS,因此其major和minor分别为0x03和0x01。接下来,我们看一下握手头:
其中握手类型分别为:
Client hello:0x01
Server hello:0x02莫扎特k310
Certificate:0x0b
Server key exchange:0x0c
Certificate request:0x0d
Server hello done:0x0e
Certificate verify:0x0f
Client key exchange:0x10
Finish:0x14
1.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->Serverjomo
|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连接的安全性在于其建立安全通路的方式和建立后的安全性,其缺点
就是消耗大量的资源。
    再往下一行是一个packet id和一个时间戳,这两个字段一共占据8个字节,它有效的防止了重放攻击。再往后一行,为一个单字节0x00,可见第一个数据包并不想确认任何数据,这也是正常的。最后是一个包序列号,占据4个字节,为0,每个方向的非确认包(P_ACK),都拥有一个序列号,这个序列号是用于保证传输的,并不是用于防止重放攻击的,注意,它和packet id的意义是不同的,确认包并不包含序列号。
四川省工商行政管理局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,表示服务器使用第二类密钥交换算法,这样就和客户端达成了一致。第二行是一个session id,这是另一方向的session id。后面的数据意义和第一个包是一样的。最后一行,也是一个4字节的0,这表示在从服务器端到客户端这个方向上,这是第一个数据包。
    值得注意的是,我们看第5行,第一个字节为1,说明有一个数据包确认,紧接着4个字节为0,说明它确认的是Client到Server方向的第一个数据包,再往后的8个字节是Client到Server方向的session id。
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,也就是Client hello,它的长度是后面的3个字节。最终,我们发现,这个OpenVPN协议封装的数据载荷就是SSL握手消息中的Client hello消息。

本文发布于:2024-09-23 15:25:44,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/136995.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:协议   握手   数据包   密钥   数据   序列号   协商   建立
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议