如果您无法下载资料,请参考说明:
1、部分资料下载需要金币,请确保您的账户上有足够的金币
2、已购买过的文档,再次下载不重复扣费
3、资料包下载后请先用软件解压,在使用对应软件打开
学习一种协议的最好的方式就是研究它的数据包,这样可以加深对协议的理解。对于研究过某种协议数据包的家伙来讲,他一定知道协议头的哪个位置对应哪个字段,虽然这对于理解协议为什么这么设计可能没有太大的帮助,然而对于排查问题和实际实施是很有帮助的。既然很多人都对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,且本文解析的数据包也是基