SSL/TLS协议交互流程分析

本文参考

SSL/TLS协议运行机制的概述

tls运行机制,这里不细说,建议细看

HTTPS与TLS

The Transport Layer Security (TLS) Protocol v1.2

ssl/tls基础介绍

SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密。

1. 认证用户和服务器,确保数据发送到正确的客户机和服务器。

2. 加密数据以防止数据中途被窃取。

3. 维护数据的完整性,确保数据在传输过程中不被改变。

sl协议结构体

ssl协议结构

SSL位于应用层和传输层之间,它可以为任何基于TCP等可靠连接的应用层协议提供安全性保证。

1. SSL握手协议:是SSL协议非常重要的组成部分,用来协商通信过程中使用的加密套件(加密算法、密钥交换算法和MAC算法等)、在服务器和客户端之间安全地交换密钥、实现服务器和客户端的身份验证。

2. SSL密码变化协议:客户端和服务器端通过密码变化协议通知对端,随后的报文都将使用新协商的加密套件和密钥进行保护和传输。

3. SSL警告协议:用来向通信对端报告告警信息,消息中包含告警的严重级别和描述。

4. SSL记录协议:主要负责对上层的数据(SSL握手协议、SSL密码变化协议、SSL警告协议和应用层协议报文)进行分块、计算并添加MAC值、加密,并把处理后的记录块传输给对端

密算法

1. 散列(Hash)
把任意大小的文档变成一个 固定大小(MD5是32个字符)的字符串,过程不可逆。MD5,SHA1等。

2. 对称加密(Symmetric Cryptography)
使用同一个密钥加密和解密,优点是速度快,缺点是密钥管理不方便,要求共享密钥。 DES,AES等。

3. 非对称加密(Asymmetric Cryptography)
使用公钥和私钥来加密和解密,优点是密钥管理很方便,缺点是速度慢。RSA,DSA等。

4. 数字签名(Digital Signature)
使用散列和非对称加密验证文档的真实性。先为要签名的信息生成一个Hash字串,Hash1,然后用你的私钥加密得到Encrypted(Hash1),这就是你对这个文档的数字签名。
当别人需要验证某个文档是否是你签名的时候,只需要用你的公钥解密你的签名得到Hash1,并和该文档计算出来的Hash2对比,查看是否一致。如果一致则说明你确实对该文档签过名,否则就是没有。

证方式

单向认证

客户端向服务器发送消息,服务器接到消息后,用服务器端的密钥库中的私钥对数据进行加密,然后把加密后的数据和服务器端的公钥一起发送到客户端,客户端用服务器发送来的公钥对数据解密,然后在用传到客户端的服务器公钥对数据加密传给服务器端,服务器用私钥对数据进行解密,这就完成了客户端和服务器之间通信的安全问题,但是单向认证没有验证客户端的合法性。

双向认证

(1)客户端向服务器发送消息,首先把消息用客户端证书加密然后连同时把客户端证书一起发送到服务器端

(2)服务器接到消息后用首先用客户端证书把消息解密,然后用服务器私钥把消息加密,把服务器证书和消息一起发送到客户端

(3)客户端用发来的服务器证书对消息进行解密,然后用服务器的证书对消息加密,然后在用客户端的证书对消息在进行一次加密,连同加密消息和客户端证书一起发送到服务器端,

(4)到服务器端首先用客户端传来的证书对消息进行解密,确保消息是这个客户发来的,然后用服务器端的私钥对消息在进行解密这个便得到了明文数据。

一、下图为客户端和服务端的通信流程

双向通信交互流程

图中包括服务端和客户端电子证书请求认证,下面我们分析的例子不包含请求客户端证书认证

二、后台程序https tls/1.2验证测试

下面为程序中的客户端和服务端具体交互信息。通过curl命令访问api接口:

root@sdn112:~# curl -1 --tlsv1.2 --cacert /root/ca.crt -X 'GET'  -v https://192.168.30.145:9131/v2.0/networks | python -mjson.tool
* Hostname was NOT found in DNS cache
*   Trying 192.168.30.145...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 192.168.30.145 (192.168.30.145) port 9131 (#0)
* successfully set certificate verify locations:
*   CAfile: /root/ca.crt
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Server hello (2):
{ [data not shown]
* SSLv3, TLS handshake, CERT (11):
{ [data not shown]
* SSLv3, TLS handshake, Server key exchange (12):
{ [data not shown]
* SSLv3, TLS handshake, Server finished (14):
{ [data not shown]
* SSLv3, TLS handshake, Client key exchange (16):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Finished (20):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
{ [data not shown]
* SSLv3, TLS handshake, Finished (20):
{ [data not shown]
* SSL connection using ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
*    subject: C=cn; ST=hb; O=fiberhome; OU=fitos; CN=192.168.30.145
*    start date: 2017-09-21 09:29:38 GMT
*    expire date: 2018-09-21 09:29:38 GMT
*    common name: 192.168.30.145 (matched)
*    issuer: C=cn; ST=hb; L=wh; O=fiberhome; OU=fitos; CN=192.168.30.145
*    SSL certificate verify ok.
> GET /v2.0/networks HTTP/1.1
> User-Agent: curl/7.35.0
> Host: 192.168.30.145:9131
> Accept: */*
>
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0< HTTP/1.1 200 OK
< Content-Length: 399
< Content-Type: application/json; charset=UTF-8
< Vimid: 10a24b40-90ce-43c9-a225-edde2587ff39
< Date: Thu, 28 Sep 2017 04:06:50 GMT
<
{ [data not shown]
100   399  100   399    0     0    893      0 --:--:-- --:--:-- --:--:--   892
* Connection #0 to host 192.168.30.145 left intact
{
    "networks": [
        {
            "NetID": "a851428d-e500-4d11-b266-364035d36e28",
            "adminStateUp": true,
            "external": false,
            "netName": "net1",
            "networkType": "vxlan",
            "physicalNetwork": null,
            "segmentationID": "1057",
            "self": "/v1/networks/a851428d-e500-4d11-b266-364035d36e28",
            "shared": false,
            "status": "ACTIVE",
            "subnets": [
                "2119c378-435f-473c-a59a-d99f79c8dccf"
            ],
            "tenentId": "8c967359b4bd4be2b7989bb0d9524f56"
        }
    ]
}

时在发送端网卡抓包查看客户端和服务端tls加密交互过程:

root@sdn112:~# ssldump -i br-ex
New TCP connection #1: 192.168.30.26(43449) <-> 192.168.30.145(9131) 
1 1  0.0016 (0.0016)  C>S  Handshake
      ClientHello
        Version 3.3
        cipher suites
        Unknown value 0xc030
        Unknown value 0xc02c
        Unknown value 0xc028
        Unknown value 0xc024
        Unknown value 0xc014
        Unknown value 0xc00a
        Unknown value 0xa3
        Unknown value 0x9f
        Unknown value 0x6b
        Unknown value 0x6a
        TLS_DHE_RSA_WITH_AES_256_CBC_SHA
        TLS_DHE_DSS_WITH_AES_256_CBC_SHA
        Unknown value 0x88
        Unknown value 0x87
        Unknown value 0xc032
        Unknown value 0xc02e
        Unknown value 0xc02a
        Unknown value 0xc026
        Unknown value 0xc00f
        Unknown value 0xc005
        Unknown value 0x9d
        Unknown value 0x3d
        TLS_RSA_WITH_AES_256_CBC_SHA
        Unknown value 0x84
        Unknown value 0xc012
        Unknown value 0xc008
        TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
        TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
        Unknown value 0xc00d
        Unknown value 0xc003
        TLS_RSA_WITH_3DES_EDE_CBC_SHA
        Unknown value 0xc02f
        Unknown value 0xc02b
        Unknown value 0xc027
        Unknown value 0xc023
        Unknown value 0xc013
        Unknown value 0xc009
        Unknown value 0xa2
        Unknown value 0x9e
        TLS_DHE_DSS_WITH_NULL_SHA
        Unknown value 0x40
        TLS_DHE_RSA_WITH_AES_128_CBC_SHA
        TLS_DHE_DSS_WITH_AES_128_CBC_SHA
        Unknown value 0x9a
        Unknown value 0x99
        Unknown value 0x45
        Unknown value 0x44
        Unknown value 0xc031
        Unknown value 0xc02d
        Unknown value 0xc029
        Unknown value 0xc025
        Unknown value 0xc00e
        Unknown value 0xc004
        Unknown value 0x9c
        Unknown value 0x3c
        TLS_RSA_WITH_AES_128_CBC_SHA
        Unknown value 0x96
        Unknown value 0x41
        Unknown value 0xff
        compression methods
                  NULL
1 2  0.0148 (0.0131)  S>C  Handshake
      ServerHello
        Version 3.3
        session_id[32]=
          08 2d cc a8 1a 4a ac 41 d9 74 94 11 20 49 4a da
          23 7e 21 0f 32 98 96 14 c1 a9 88 d3 78 00 6c b4
        cipherSuite         Unknown value 0xc030
        compressionMethod                   NULL
1 3  0.0148 (0.0000)  S>C  Handshake
      Certificate
1 4  0.0148 (0.0000)  S>C  Handshake
      ServerKeyExchange
1 5  0.0148 (0.0000)  S>C  Handshake
      ServerHelloDone
1 6  0.0171 (0.0023)  C>S  Handshake
      ClientKeyExchange
1 7  0.0171 (0.0000)  C>S  ChangeCipherSpec
1 8  0.0171 (0.0000)  C>S  Handshake
1 9  0.0209 (0.0037)  S>C  ChangeCipherSpec
1 10 0.0209 (0.0000)  S>C  Handshake
1 11 0.0213 (0.0003)  C>S  application_data
1 12 0.8137 (0.7924)  S>C  application_data
1 13 0.8142 (0.0004)  C>S  Alert
1    0.8143 (0.0000)  C>S  TCP FIN
1    0.8149 (0.0006)  S>C  TCP FIN

面过程服务器就没有要求客户端发送客户端电子证书进行身份认证。从认证过程看,https协商采用TLS1.2/SSL3.3版本,整个握手交互流程都有,加密成功后,客户端和服务端的http报文就进行加密传输,然后通过公共密钥计算私有密钥进行解密。这里就可以验证后台进程可以支持https tls1.2

三、tls 1.2运行交互消息分析

下面我们对比分析访问https://www.baidu.com的交互过程,抓包分析详细的消息体内容,抓包信息如下: 
完整抓包
如上图,前面第一个红框即为客户端和服务端的通过tcp标志位中的syn/ack的进行三次tcp握手连接,后面红框为http请求结束后,通过fin/ack关闭tcp连接,中间为采用tls协议建立加密通信的过程,并完成http请求的接受和响应。

具体加密通道的协商过程如下:

3.1 客户端发出请求(ClientHello)

client hello

客户端与服务端通过tcp三次握手建立tcp连接后,客户端首先向服务器发出建立加密通信的请求,发送ClientHello请求,从消息体结构看,tls/ssl是基于tcp连接之上,应用层之下的协议,封装的消息体内容如下:

(1) 此时握手协议(handshake protocol)的消息类型为:client hello
(2) 支持的TLS协议版本,比如TLS 1.0版。握手协议的版本为TLS 1.2
(3) 一个客户端生成的随机数,稍后用于生成"对话密钥"。
(4) 支持的加密套件,如Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
(5) 支持的压缩方法。
(6) 扩展属性如:服务器名称(例子中为baidu.com),支持的签名算法等
 2006年,TLS协议加入了一个Server Name Indication扩展,允许客户端向服务器提供它所请求的域名。

.2 服务器响应(SeverHello)

服务器收到客户端请求后,向客户端发出响应,叫做Sever Hello。

server hello

从消息体中,可以看到服务器的响应包含以下内容:

(1) 确认使用的加密通信协议版本,这里确认使用tls1.2,而不是client hello中的tls1.1。响应握手协议消息 server hello。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。
(2) 一个服务器生成的随机数,稍后用于生成"对话密钥"。
(3) 确认使用的加密套件,这里为rsa+aes128+sha256
(4) 压缩方法为空。
(5) 一些列扩展信息

了上面这些信息,如果服务器需要确认客户端的身份,就会再包含一项请求,要求客户端提供”客户端证书”。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供USB密钥,里面就包含了一张客户端证书。

3.3 服务端发送服务端电子证书(CA),密钥交换(server key exchange),及server hello done三个握手消息

客户端接收到server hello握手消息后,及时反馈ack消息。服务端接收客户端ack消息后,发送服务端电子证书,密钥交换,及server hello done三个握手消息

ca

封装内容看,包含两层ssl协议体信息,头一个为服务端证书,后面跟着公共密钥交换和hello done消息体,具体如下:

(1)详细的电子证书信息和CA认证机构信息
(2)密钥交换信息,包括DH算法计算出的pubkey公钥,电子签名的hash算法值
(3)server hello done消息体

涉及到两个问题:

(1)如何保证公钥不被篡改?
解决方法:将公钥放在数字证书中。只要证书是可信的,公钥就是可信的。所以上面报文中就将服务端CA证书和公共密钥交换消息放在同一个tcp连接进行传输。

(2)公钥加密计算量太大,如何减少耗用的时间?
解决方法:每一次对话(session),客户端和服务器端都生成一个"对话密钥"(session key),整个对话密钥是通过公共密钥和生成的3个随机数计算得到,用它来加密信息。由于"对话密钥"是对称加密,所以运算速度非常快,而服务器公钥只用于加密"对话密钥"本身,这样就减少了加密运算的消耗时间。

.4 客户端发送密钥交换信息(client key exchange)、编码改变协议消息(change cipher spec)

客户端发送ack消息给服务端,确认收到server hello done消息,然后发送客户端的密钥交换信息和修改密钥的协议消息

client key exchange

主要内容如下:

(1) 发送DH算法计算的pubkey,用于服务端计算生成解密私钥
(2) 发送编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
(3) 发送加密后的握手消息,一个随机数。该随机数用服务器公钥加密,防止被窃听
(4) 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验。(可能在加密消息中,未确认)

端收到服务器所有响应消息后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。 
如果证书没有问题,客户端就会从证书中取出服务器的公钥,即server key exchange消息中携带的pubkey值。然后,根据根据已经收到的三个随机数计算书加密密钥,对握手信息进行加密通信,然后向服务器发送上面抓包中三项信息内容。

该步骤中的随机数,是整个握手阶段出现的第三个随机数,又称”pre-master key”。有了它以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把”会话密钥”。

至于为什么一定要用三个随机数,来生成"会话密钥",dog250解释得很好:
"不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。
对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。
pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素。
那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。"

此外,如果前一步,服务器要求客户端证书,客户端会在这一步同样也发送证书及相关信息。更加详细信息参考HTTPS与TLS

3.5 服务器的最后回应

cepher
服务器收到客户端的第三个随机数pre-master key之后,计算生成本次会话所用的”会话密钥”。然后,向客户端最后发送下面信息。

(1)编码改变协议,表示随后的信息都将用双方商定的加密方法和密钥发送。
(2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验。

至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用”会话密钥”加密内容。

最后从抓包的报文我们可以看到:Http请求处理响应结束后,客户端会发送加密的alert消息给服务端,告知如果异常产生变化,就要发出告警。最后就是客户和服务端发送fin/ack tcp消息关闭tcp连接

猜你喜欢

转载自blog.csdn.net/chasonli666/article/details/89278600