愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

【译文】SSL/TLS会话的流量分析

一、前言

本文主要探讨当我们使用SSL/TLS时,在协议级别发生了什么。为了便于分析,我将会使用一个基于OpenSSL所实现的非阻塞式TCP客户端。
我们首先要记住,SSL/TLS能让应用像底层基础设施(指的是网络主机)一样安全,确保通信的安全是它唯一的职责。它介于应用层协议(通常是HTTP,但也可以用于其他应用层协议)和传输层协议TCP)之间的一种独立协议。使用TLS仅需要对上层协议下层协议做很少的变更,因此它可以做到几乎对用户是无感知的,也就是说用户察觉不到这个协议已经默默生效了。当然,这也带来了一些弊端,它在一些基础方面对协议做了限制(比如就不支持UDP)。
SSL/TLS诞生至今,已经有了很大的改变。如今SSL2.03.0被认为是不安全的,因此我们现在一般使用较新的TLS 1.0TLS 1.1TLS 1.2版本。这些协议的历史是一个很有趣的话题。


二、协议的描述

如前文提到的那样,TLS协议位于应用层传输层之间。并且在其内部还划分了两个主要的子层。如下是协议的一个总体结构图,可以展示出它在网络协议栈中的位置:

下面的子层位于TCP之上,因为TCP是个面向连接的、可靠的传输层协议。这一层主要包括TLS记录协议(TLS Record Protocol)。通过TLS记录协议,来自上面的子层的数据首先会被分块为最大2^14字节的片段。然后对这些数据进行压缩(可选的过程),并添加报文认证码Message Authentication Code),最终根据协商的加密细则对数据进行加密并添加一个SSL记录头。
值得的是,每一个数据块都会被封装到一个结构体中,并且这个结构体中不会保留客户端消息的分界信息,这意味着同样类型的消息可能会被合并为到一个结构体中。
下面这个图表展示了构建一个SSL记录的过程:

------+
 data |-----> 1. 分段数据
------+       +------------------+
              |                  |
              +------------------+
              2. 压缩数据 (不过实践中通常不压缩)
              +------------------+-----+
              |                  | MAC |   添加`报文鉴别码`
              +------------------+-----+
              3. 加密数据
              +------------------------+
              |                        |   变为密文
              +------------------------+
              4. 添加头部 (TLS记录头)
         +----+------------------------+
         |    |                        |
         +----+------------------------+
         TLS记录头

上面的子协议则建立在TLS记录协议之上,它包含了4个子协议。每个子协议都有非常明确的目的,用于通信的不同阶段:

1、握手协议 (Handshake Protocol)

握手协议使双方可以互相认证、以及为本次连接协商加密套件和其他连接参数。TLS握手协议涉及到客户端服务器之间的四组消息交换。每一组通常都在独立的TCP段中传输。以下图表展示了对该过程的一个总结,其中有多个步骤,部分步骤是可选的。需要注意的是,ChangeCipherSpec报文不属于该协议,它自身就是一个协议。

客户端                                     服务端
+---+                                     +---+
|   |                                     |   |
|   | ClientHello                         |   |
|   o------------------------------------>|   |
|   |                                     |   |
|   | ServerHello                         |   |
|   | [Certificate]                       |   |
|   | [ServerKeyExchange]                 |   |
|   | [CertificateRequest]                |   |
|   | ServerHelloDone                     |   |
|   |<------------------------------------o   |
|   |                                     |   |
|   | [Certificate]                       |   |
|   | ClientKeyExchange                   |   |
|   | [CertificateVerify]                 |   |
|   | ** ChangeCipherSpec **              |   |
|   | Finished                            |   |
|   o------------------------------------>|   |
|   |                                     |   |
|   | ** ChangeCipherSpec **              |   |
|   | Finished                            |   |
|   |<------------------------------------o   |
|   |                                     |   |
+---+                                     +---+

其中可选的步骤有:

  • Certificate (服务端): 除了匿名密钥交换算法外,使用其他的密钥交换算法中都需要该步骤
  • ServerKeyExchange: 在一些是情况下(如使用了迪菲赫尔曼(Diffie-Hellman)算法时)需要该步骤
  • CertificateRequest: 需要对客户端进行认证时需要该步骤
  • Certificate (客户端): 作为对CertificateRequest的响应时需要该步骤(也就是说是和CertificateRequest配套使用的)
  • CertificateVerify: 如果发送了客户端Certificate报文,则需要该步骤

2、加密组件生效协议 (ChangeCipherSpec Protocol)

使之前协商的参数生效,从而使通信变为加密的

3、告警协议 (Alert Protocol)

用来传达异常信息和指示潜在的安全问题

4、应用数据协议 (Application Data Protocol)

接收来自应用层任意大小的数据,将之喂给安全通道。
多个报文会被合并为一条记录层报文,但是这些报文必须属于同种子协议。因此,以上四种协议都必须是自定界(Self-delimiting)的(例如:必须包含自己的长度字段)


三、记录协议格式

记录协议包含了三个字段,TLS高层则建立在此的基础上:

  • 第0个字节: TLS记录类型
  • 第1-2个字节: TLS版本号(一个字节主版本号,一个字节次版本号)
  • 第3-4个字节: 记录数据的长度(不包含头部),最大支持16384Bit(也就是16KB

它的结构如下:

   记录类型 (1B)
    /   版本 (1B主版本号,1B次版本号)
   /    /         长度 (2B)
  /    /          /
+----+----+----+----+----+
|    |    |    |    |    |
+----+----+----+----+----+

其中,记录类型的取值有:

记录类型                 十进制取值   十六进制取值
---------------------------------------------
CHANGE_CIPHER_SPEC            20         0x14
ALERT                         21         0x15
HANDSHAKE                     22         0x16
APPLICATION_DATA              23         0x17

版本的取值有:

版本值                   十进制取值   十六进制取值
---------------------------------------------
SSL 3.0                      3,0       0x0300
TLS 1.0                      3,1       0x0301
TLS 1.1                      3,2       0x0302
TLS 1.2                      3,3       0x0303

1、握手协议帧格式

握手协议是TLS中最为复杂的子协议。TLS规范也主要聚焦于此,因为它处理了建立一个安全连接所该做的所有机制。下面的图表展示了握手协议报文总体的一个结构。在TLS规范中,总共有10中握手报文类型(不包含扩展类型):

                       |
记录层                  | 握手层                          |
                       |                                | ...more messages
+------+---+---+---+---+---+---+---+---+--- - - - - - --+---
| 0x16 |   |   |   |   |   |   |   |   | message body   |
+------+---+---+---+---+---+---+---+---+--- - - - - - --+---
                       | \ |<--------->|
                       |  \ 握手报文长度 (3B)        
                           \
                           type

其中,握手层里的类型有:

握手类型取值                十进制取值    十六进制取值
------------------------------------------------
HELLO_REQUEST                    0          0x00
CLIENT_HELLO                     1          0x01
SERVER_HELLO                     2          0x02
CERTIFICATE                     11          0x0b
SERVER_KEY_EXCHANGE             12          0x0c
CERTIFICATE_REQUEST             13          0x0d
SERVER_DONE                     14          0x0e
CERTIFICATE_VERIFY              15          0x0f
CLIENT_KEY_EXCHANGE             16          0x10
FINISHED                        20          0x14

接下来,我们将对每一种类型的报文格式进行说明:

(1)HelloRequest

可以让服务器重启握手协商,但是不常用。如果一次连接挂起了足够久,那么它的安全性就会逐渐减弱,因此服务器可以使用这种报文来迫使客户端使用新的会话密钥重新协商

     |
     | 握手层 
- ---+---+---+---+---+
   4 | 0 | 0 | 0 | 0 |
- ---+---+---+---+---+
  /    \ |<--------->|
 /      \  报文长度:0
记录长度 握手类型
(2)ClientHello

这种报文通常用来开始一次TLS握手协商,它会携带客户端支持的加密组件列表(让服务端能够从其中挑出最适合的一个,不过通常是最安全的那个)、压缩算法列表扩展列表。此外,通过包含SessionId字段,也给客户端提供了重启上次会话的可能性。

     |
     | 握手层
- ---+------+--+--+--+---+---+--- - - ---+---+-- - - - ---+-- - - - - ---+-- - - - - --+-- - - - - --+
     | 0x01 |  |  |  | 3 | 1 | 32 Bytes  |   | max 32 bit | CipherSuites | Compression | Extensions  |
- ---+------+--+--+--+---+---+--- - - ---+---+-- - - - ---+-- - - - - ---+-- - - - - --+-- - - - - --+
   / |  \   |<------>|<----->|     \       \          \
  /      \   报文长度  SSL/TLS版本    \   sessionId长度   \
记录长度   \         (这儿是TLS1.0)    \                   \
         类型                       32B随机数        sessionId(只有sessionId>0时存在)

加密组件(Cipher Suites)

+----+----+----+----+----+----+
|    |    |    |    |    |    |
+----+----+----+----+----+----+
|<------->|<------->|<------->|
    长度    加密组件ID 加密组件ID

压缩算法(Compression Methods)
以下是压缩算法桢部分,但是目前实践中并没有特定的实现是使用压缩的

+---+---+---+
| 0 | 1 | 0 |
+---+---+---+
|<----->|  \
  长度       \
(当前是1)   压缩算法ID(当前是0)

扩展部分(Extensions)

+----+----+----+----+----+----+--- - - - - - --- 
|    |    |    |    |    |    | Extension Data
+----+----+----+----+----+----+--- - - - - - ---
|<------->|<------->|<------->|
    长度     扩展ID   扩展数据长度
(3)ServerHello

ServerHelloClientHello非常类似,除了它只包含一个加密组件和一个压缩算法。如果它包含一个SessionId(也就是SessionId长度大于0),表明指示客户端在将来复用这次会话。

     |
     | 握手层
- ---+------+--+--+--+---+---+--- - - ---+---+-- - - - - -+---+---+---+-- - - - - --+
     | 0x02 |  |  |  | 3 | 1 | 32 Bytes  |   | max 32 bit |   |   |   | Extensions  |
- ---+------+--+--+--+---+---+--- - - ---+---+-- - - - - -+---+---+---+-- - - - - --+
   / |  \   |<------>|<----->|      \       \           \ |<----->|  \
  /      \   报文长度  SSL/TLS版本  32B随机数 sessionId长度 \  加密组件   \
记录长度  类型         (这儿是TLS1.0)                        \          压缩算法
                                                      sessionId
                                                (只有sessionId>0时存在)
(4)Certificate

报文主体中包含了一个公钥证书链,证书链可以让TLS支持证书分层和公钥基础设施(PKI,Public Key Infrastructures)

     |
     | 握手层
- ---+------+---+---+---+---+---+---+---+---+---+--- - - - ---+--------- - - - ---
     | 0x0b |   |   |   |   |   |   |   |   |   | certificate | More certificate
- ---+------+---+---+---+---+---+---+---+---+---+--- - - - ---+--------- - - - ---
   / |  \   |<--------->|<--------->|<--------->|
  /      \      长度       证书串长度    证书长度
记录长度  类型
(5)ServerKeyExchange

这个报文携带了客户端需要从服务器获得的密钥交换算法参数,以便用于之后的对称加密。这是可选的,因为不是所有的密钥交换都需要服务器明确地发送这个报文。实际上在大多数情况下,Certificate报文就足以让客户端安全地和服务器交换预主密钥(Premaster Key)了,这些参数的格式只取决于已选的加密组件,即之前通过ServerHello报文设置的

     |
     | 握手层
- ---+------+----+----+----+----------------+
     | 0x0c |    |    |    |   parameters   |
- ---+------+----+----+----+----------------+
  /  |  \   |<------------>|            \
 /       \         长度                   \
 记录长度  类型                          算法参数
(6)CertificateRequest

当服务端需要客户端身份验证时使用,在Web服务器中不常用,但是在一些情况下却非常有用。这种报文不仅向客户端询问证书,也会告知哪些证书类型是可接受的。除此之外,它也表明了哪些证书机构是可靠的。

     |
     | 握手层
- ---+------+----+----+----+----+----+-- - - - - - --+----+----+----+----+----------+-- - -
     | 0x0d |    |    |    |    |    |               |    |    |    |    |          |
- ---+------+----+----+----+----+----+-- - - - - - --+----+----+----+----+----------+-- - -
   / |  \   |<------------>|  \                      |<------->|<------->|<-------->|
  /      \        长度          \                      CA机构数量  CA信息长度  CA唯一名称
记录长度  类型                证书类型长度
(7)ServerHelloDone

这个报文能够结束服务器部分的握手协商,它没有任何附加信息

      |
      | 握手层
- ----+------+----+----+----+
    4 | 0x0e | 0  | 0  | 0  |
- ----+------+----+----+----+
   /  |  \   |<------------>|
  /       \        长度:0
记录长度   类型
(8)ClientKeyExchange

提供给服务器必要的信息,用以生成对称加密的密钥。这种报文格式和ServerKeyExchange非常类似,因为它很大程度上取决于服务端通过密钥交换算法所选取的密钥

      |
      | 握手层
- ----+------+----+----+----+--- - - - - ---+
      | 0x10 | 0  | 0  | 0  |               |
- ----+------+----+----+----+--- - - - - ---+
   /  |  \   |<------------>|<------------->|
  /       \        长度           算法参数
记录长度   类型
(9)CertificateVerify

这种报文被客户端用来向服务端证明它持有公钥证书所对应的私钥。该报文持有客户端数字签名的散列信息。如果服务端向客户端发起了CertificateRequest,则需要发送待验证的证书。再者,信息确切的尺寸和结构取决于所商定的算法,在多数情况下,输入到散列函数的信息是相同的。

      |
      | 握手层
- ----+------+----+----+----+--- - - - - ---+
      | 0x1f |    |    |    |               |
- ----+------+----+----+----+--- - - - - ---+
   /  |  \   |<------------>|<------------->|
  /       \        长度         签名过的Hash
记录长度   类型
(10)Finished

这种报文指示TLS协商结束并且加密组件已经激活。因为协商已经完成了,所以它应该在加密后被发送。因此加密协议生效(ChangeCipherSpec Protocol)报文必须在此之前发送,才能够激活加密。Finished报文包含了用于所有先前握手报文组合的Hash,其后则是识别服务器/客户端角色的特殊号码、主密钥和填充。最终的Hash和CertificateVerify中所用的Hash不同,因为自那之后包含了更多的握手报文。

      |
      | 握手层
- ----+------+----+----+----+--- - - - - ---+
      | 0x14 |    |    |    |               |
- ----+------+----+----+----+--- - - - - ---+
   /  |  \   |<------------>|<------------->|
  /       \        长度         签名过的Hash
记录长度   类型


四、加密组件生效协议(ChangeCipherSpec)格式

(ChangeCipherSpec)格式
这个是最简单的子协议了,因为它只有一种报文。之所以这种报文要独立成为一个协议而不是作为握手报文的一部分,是因为记录层封装的关系。TLS协议会立即对整个记录层进行加密。然后ChangeCipherSpec报文指示了密文的激活状态,因为加密不能只作用于部分报文,所以对任何其他的报文而言是不可能跟在ChangeCipherSpec之后的。最好的办法就是避免这种结合状态,也就是将这种报文提取为一种独立的协议。
如下则是ChangeCipherSpec报文的结构:

                           |
记录层                      | ChangeCipherSpec层
+------+----+----+----+----+----+
| 0x14 |    |    |  0 |  1 |  1 |
+------+----+----+----+----+----+
    /            |<------->|
   /                 长度   
类型                        


五、告警协议(AlertProtocol)帧格式

告警协议也是相对简单的,它定义了两个字段:严重等级告警描述。第一个字段表明了告警的严重性(1是警告,2是致命错误),然后第二个字段编码了准确的触发条件。所支持的告警描述取决于SSL/TLS的版本:

                           |
记录层                      | 告警层
+------+----+----+----+----+----+----+
| 0x15 |    |    |  0 |  2 |    |    |
+------+----+----+----+----+----+----+
                 |<------->|
                     长度

以下是严重等级

告警严重性              十进制数值  十六进制数值
-------------------------------------------
WARNING                       1        0x01
FATAL                         2        0x02

以下则是TLS1.0所支持的告警描述:

告警描述                    十进制数值  十六进制数值
-----------------------------------------------
CLOSE_NOTIFY                      0        0x00
UNEXPECTED_MESSAGE               10        0x0A
BAD_RECORD_MAC                   20        0x14
DECRYPTION_FAILED                21        0x15
RECORD_OVERFLOW                  22        0x16
DECOMPRESSION_FAILURE            30        0x1E
HANDSHAKE_FAILURE                40        0x28
NO_CERTIFICATE                   41        0x29
BAD_CERTIFICATE                  42        0x2A
UNSUPPORTED_CERTIFICATE          43        0x2B
CERTIFICATE_REVOKED              44        0x2C
CERTIFICATE_EXPIRED              45        0x2D
CERTIFICATE_UNKNOWN              46        0x2E
ILLEGAL_PARAMETER                47        0x2F
UNKNOWN_CA                       48        0x30
ACCESS_DENIED                    49        0x31
DECODE_ERROR                     50        0x32
DECRYPT_ERROR                    51        0x33
EXPORT_RESTRICTION               60        0x3C
PROTOCOL_VERSION                 70        0x46
INSUFFICIENT_SECURITY            71        0x47
INTERNAL_ERROR                   80        0x50
USER_CANCELLED                   90        0x5A
NO_RENEGOTIATION                100        0x64


六、应用数据(ApplicationData)协议帧格式

这个协议的使命是将来自应用层的数据进行恰当地封装,以便下层的协议(如TCP)可以无缝地处理这些数据,而无需迫使下层协议去做一些改变。本协议的报文格式如下:

                           |
记录层                      | 应用数据层(加密后)
+------+----+----+----+----+----+----+-- - - --+-- - - --+
| 0x17 |    |    |    |    |    |    |         |         |
+------+----+----+----+----+----+----+-- - - --+-- - - --+
   /                /      |<----------------->|<------->|
  /                /       | 长度自定界数据           MAC
类型         长度:任意(最多16k)


七、分析SSL/TLS流量

流量分析的主要目的是测试我当前为 Gambit Scheme compiler 所做的TLS客户端实现。我将使用Wireshark来抓包,客户端将基于Scheme,具有SSL/TLS的工作进度支持,以及使用作为OpenSSL发行版的一部分的测试服务器(带有证书)。服务器监听443端口,并且所有的通信都会通过回环设备完成。在视图里查看TLS包最简单的方式是在Wireshark里使用协议过滤器(protocol filter),将值设为ssl

(1)第一个包(客户端->服务端)

一旦服务端运行起来等待连接后,客户端就可以发起第一次握手。以下是客户端发送的第一个包的一个示例:

 Full contents of the packet

 0000   02 00 00 00 45 00 00 98 13 ed 40 00 40 06 00 00  ....E.....@.@...
 0010   7f 00 00 01 7f 00 00 01 ec 26 01 bb 43 7c ee 74  .........&..C|.t
 0020   60 b5 50 0a 80 18 31 d7 fe 8c 00 00 01 01 08 0a  `.P...1.........
 0030   21 62 1e 1e 21 62 1e 1e 16 03 01 00 5f 01 00 00  !b..!b......_...
 0040   5b 03 01 54 9a ab 72 98 65 11 2f da 9e cf c9 db  [..T..r.e./.....
 0050   6c bd 4b 4c 56 4b 0c a5 68 2b aa 60 1f 38 66 e7  l.KLVK..h+.`.8f.
 0060   87 46 b2 00 00 2e 00 39 00 38 00 35 00 16 00 13  .F.....9.8.5....
 0070   00 0a 00 33 00 32 00 2f 00 9a 00 99 00 96 00 05  ...3.2./........
 0080   00 04 00 15 00 12 00 09 00 14 00 11 00 08 00 06  ................
 0090   00 03 00 ff 01 00 00 04 00 23 00 00              .........#..

 ------------

 Family: IP

 0000   02 00 00 00                                      ....

 IP protocol

 0000   45 00 00 98 13 ed 40 00 40 06 00 00 7f 00 00 01  E.....@.@.......
 0010   7f 00 00 01                                      ....

 TCP protocol

 0000   ec 26 01 bb 43 7c ee 74 60 b5 50 0a 80 18 31 d7  .&..C|.t`.P...1.
 0010   fe 8c 00 00 01 01 08 0a 21 62 1e 1e 21 62 1e 1e  ........!b..!b..

 ------------

 TLSv1 protocol

 0000   16 03 01 00 5f 01 00 00 5b 03 01 54 9a ab 72 98  ...._...[..T..r.
 0010   65 11 2f da 9e cf c9 db 6c bd 4b 4c 56 4b 0c a5  e./.....l.KLVK..
 0020   68 2b aa 60 1f 38 66 e7 87 46 b2 00 00 2e 00 39  h+.`.8f..F.....9
 0030   00 38 00 35 00 16 00 13 00 0a 00 33 00 32 00 2f  .8.5.......3.2./
 0040   00 9a 00 99 00 96 00 05 00 04 00 15 00 12 00 09  ................
 0050   00 14 00 11 00 08 00 06 00 03 00 ff 01 00 00 04  ................
 0060   00 23 00 00                                      .#..

 TLSv1 Record protocol

 0000   16 03 01 00 5f                                   ...._

        16             Handshake protocol type
        03 01          SSL version (TLS 1.0)
        5f             Record length (95 bytes)

 TLSv1 Handshake protocol

 0000   01 00 00 5b 03 01 54 9a ab 72 98 65 11 2f da 9e  ...[..T..r.e./..
 0010   cf c9 db 6c bd 4b 4c 56 4b 0c a5 68 2b aa 60 1f  ...l.KLVK..h+.`.
 0020   38 66 e7 87 46 b2 00 00 2e 00 39 00 38 00 35 00  8f..F.....9.8.5.
 0030   16 00 13 00 0a 00 33 00 32 00 2f 00 9a 00 99 00  ......3.2./.....
 0040   96 00 05 00 04 00 15 00 12 00 09 00 14 00 11 00  ................
 0050   08 00 06 00 03 00 ff 01 00 00 04 00 23 00 00     ............#..

        01             ClientHello message type
        00 00 5b       Message length
        03 01          SSL version (TLS 1.0)
        54 .. b2       32-bytes random number
        00             Session Id length
        00 2e          Cipher Suites length (46 bytes, 23 suites)
        00 39 .. ff    23 2-byte Cipher Suite Id numbers
        01             Compression methods length (1 byte)
        00             Compression method (null)
        00 04          Extensions length (4 bytes)
        00 23          SessionTicket TLS extension Id
        00 00          Extension data length (0)

(2)第二个包(服务端->客户端)

第一个包只包含了一个从客户端发往服务端的TLS握手报文(ClientHello)。而接下来的这个TCP包,是由服务端发送给客户端来作为对ClientHello报文的响应的,并且这个包携带了3个握手报文。这些报文是ServerHelloCertificate以及ServerHelloDone (没有发送ServerKeyExchange或者CertificateRequest)。在下一个数据包之后,将省略对低层协议部分(即TCP/IP

ServerHello message    

0000   16 03 01 00 35 02 00 00 31 03 01 54 9a ab 72 85  ....5...1..T..r.
0010   91 a4 a7 a9 27 fe 3d e4 da f6 38 a5 aa 6e 5a 2f  ....'.=...8..nZ/
0020   31 90 5b 41 b0 5d de d8 9d ae f6 00 00 35 00 00  1.[A.].......5..
0030   09 ff 01 00 01 00 00 23 00 00                    .......#..

       16             Handshake protocol type
       03 01          SSL version (TLS 1.0)
       35             Record length (53 bytes)

       02             ServerHello message type
       00 00 31       Message length (49 bytes)
       03 01          SSL version (TLS 1.0)
       54 9a ab 72    First 4 bytes of random (Unix time)
       85 .. f6       Last 28 bytes of the random number
       00             Session Id length
       00 35          Selected Cipher Suite (RSA with AES-256-CBC SHA)
       00             Selected compression method (null)
       00 09          Extensions length
       ff 01 00 01 00 Extension (Renegotiation Info)
       00 23 00 00    Extension (SessionTicket TLS)


Certificate message           

0000   16 03 01 01 e4 0b 00 01 e0 00 01 dd 00 01 da 30  ...............0
0010   82 01 d6 30 82 01 3f 02 01 01 30 0d 06 09 2a 86  ...0..?...0...*.
0020   48 86 f7 0d 01 01 04 05 00 30 45 31 0b 30 09 06  H........0E1.0..
0030   03 55 04 06 13 02 41 55 31 13 30 11 06 03 55 04  .U....AU1.0...U.
0040   08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 30  ...Some-State1!0
0050   1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74  ...U....Internet
0060   20 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 64   Widgits Pty Ltd
0070   30 1e 17 0d 39 39 30 35 30 31 30 31 32 36 33 35  0...990501012635
0080   5a 17 0d 39 39 30 35 33 31 30 31 32 36 33 35 5a  Z..990531012635Z
0090   30 22 31 0b 30 09 06 03 55 04 06 13 02 44 45 31  0"1.0...U....DE1
00a0   13 30 11 06 03 55 04 03 13 0a 54 65 73 74 73 65  .0...U....Testse
00b0   72 76 65 72 30 81 9f 30 0d 06 09 2a 86 48 86 f7  rver0..0...*.H..
00c0   0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81  ..........0.....
00d0   00 fa 23 7a 03 2a 27 b1 c3 09 64 ce 36 ab eb d0  ..#z.*'...d.6...
00e0   08 16 75 54 68 6f 39 2e d0 9e 81 ed 91 f8 2b 48  ..uTho9.......+H
00f0   0e 59 10 63 0e bc ff c3 1b 4f 7a 2e d2 97 45 01  .Y.c.....Oz...E.
0100   c2 fd 20 68 98 63 76 34 48 73 3d 3e a1 74 d1 13  .. h.cv4Hs=>.t..
0110   b5 30 2b 4d a6 a4 e7 17 74 9c 2e 96 e6 82 01 a3  .0+M....t.......
0120   2a 29 66 59 89 f6 6a 2e de 99 d8 cc 8d 75 4b b7  *)fY..j......uK.
0130   35 96 db 11 a0 20 60 13 59 03 77 d8 a8 1f 26 78  5.... `.Y.w...&x
0140   38 8d 78 b5 52 31 22 c8 b8 64 c3 46 5f d4 8f e0  8.x.R1"..d.F_...
0150   83 02 03 01 00 01 30 0d 06 09 2a 86 48 86 f7 0d  ......0...*.H...
0160   01 01 04 05 00 03 81 81 00 c8 0c fa c6 c0 93 c0  ................
0170   df 8d 27 da f9 17 f6 81 c1 97 99 ba ef 64 0c ca  ..'..........d..
0180   cc 2f b9 45 4d e4 6a af cd cb 12 17 00 67 28 f5  ./.EM.j......g(.
0190   d6 63 a3 3c d6 7c df f1 b8 6b a9 e5 ba 05 93 e2  .c.<.|...k......
01a0   ab 3f ec 5d 82 c6 aa 18 7b 32 ce 58 04 a2 ac f8  .?.]....{2.X....
01b0   7a 4a 8b 8d 07 95 6e 7a 23 df 7f 61 54 55 3d 32  zJ....nz#..aTU=2
01c0   13 e2 e8 95 0b 3f 18 d7 2a e9 a3 7d 7d 8b 2c d9  .....?..*..}}.,.
01d0   22 91 6e 69 bb 3f 03 7f 75 22 5f 41 22 68 9b dd  ".ni.?..u"_A"h..
01e0   ec 4c 0f f0 9e f9 b6 25 13                       .L.....%.

       16             Handshake protocol type
       03 01          SSL version (TLS 1.0)
       01 e4          Record length (443 bytes)

       0b             Certificate message type
       00 01 e0       Message length
       00 01 dd       Certificates length
       00 .. 13       Certificates data


ServerHelloDone message

0000   16 03 01 00 04 0e 00 00 00                       .........

       16             Handshake protocol type
       03 01          SSL version (TLS 1.0)
       00 04          Record length (4 bytes)

       0e             ServerHelloDone message
       00 00 00       Message length

(3)第三个包(客户端->服务端)

目前看上去都是正确的,这些包也的确和上述协议一致。现在客户端和服务端已经就使用的算法(使用RSA进行密钥交换,AES-256-CBC进行对称加密且用SHA进行报文摘要)、压缩算法(没有使用)和TLS扩展部分(SessionTicket TLS,重新协商信息)达成了共识。此外,客户端现在拥有了服务端的证书,因此它能够决定是否应该信任服务端。接下来由客户端发送的这个包携带了下列报文:ClientKeyExchangeChangeCipherSpecFinished(已经加密了)

 ClientKeyExchange message

 0000   16 03 01 00 86 10 00 00 82 00 80 2d 28 e4 30 eb  ...........-(.0.
 0010   31 35 b0 4b 5e 4c 4d c6 ee 01 f5 33 e7 f8 3f 9b  15.K^LM....3..?.
 0020   d7 53 fc 5c e0 2d d6 12 ba 55 f8 46 ab 73 d8 3d  .S.\.-...U.F.s.=
 0030   b0 0a f7 03 7f 58 e0 32 8f 91 1f b8 cf 56 aa 89  .....X.2.....V..
 0040   9e 27 84 08 ec 78 f8 74 0c d3 80 f2 ec 04 65 e1  .'...x.t......e.
 0050   3e 92 91 52 b5 5e aa 67 e9 e6 40 e9 10 67 3c 3f  >..R.^.g..@..g<?
 0060   73 f7 62 4a 0c 42 30 c1 06 6f 53 2f c2 6b d5 c8  s.bJ.B0..oS/.k..
 0070   67 6f 06 d7 92 86 6e 1d 4d dd 6b 3f b0 26 6c 25  go....n.M.k?.&l%
 0080   2c d8 81 5a 80 e0 e2 cc d1 62 9c                 ,..Z.....b.

        16             Handshake protocol type
        03 01          SSL version (TLS 1.0)
        00 86          Record length (134 bytes)

        10             ClientKeyExchange message type
        00 00 82       Message length (130 bytes)
        00 .. 9c       RSA encrypted key data (premaster secret)


 ChangeCipherSpec message

 0000   14 03 01 00 01 01                                ......

        14             ChangeCipherSpec protocol type
        03 01          SSL version (TLS 1.0)
        00 01          Message length (1 byte)

        01             ChangeCipherSpec message


 Finished message (encrypted)

 0000   16 03 01 00 30 0c c1 86 73 a4 a3 26 62 30 21 7f  ....0...s..&b0!.
 0010   c3 2f 1a 83 34 2d 57 f0 e2 0d 37 d4 51 66 08 22  ./..4-W...7.Qf."
 0020   b0 ea b4 a4 1e 81 2a fd 5f 07 47 9f b7 2c 0a dc  ......*._.G..,..
 0030   65 08 77 40 2a                                   e.w@*

        16             Handshake protocol type
        03 01          SSL version (TLS 1.0)
        00 30          Message length (48 bytes)

        0c .. 2a       Encrypted Finished message

(4)第四个包(服务端->客户端)

在客户端发送ChangeCipherSpecFinished报文后,服务端应该也做类似的事情,从而能够使用私密的对称密钥、达成共识的加密组件参数双向地开启加密通信。服务端必须发送它自己的ChangeCipherSpecFinished报文,这样握手的过程才能够被认为是成功的。很有趣的是,我们看到了其中有一个扩展,这个扩展名为无服务端TLS会话恢复Transport Layer Security Session Resumption without Server-Side State),顾名思义。你应该记得,它被要求作为我们的ClientHello的一部分,并且由服务端在ServerHello中实现。关于这个扩展协议的更多信息,则需要查阅RFC5077规范了。正如文档中所描述的,这个扩展的握手报文已经被分配了号码4

 NewSessionTicket message

 0000   16 03 01 00 aa 04 00 00 a6 00 00 00 00 00 a0 f7  ................
 0010   2f 0c fd be ce f7 96 86 ca fd da 58 d6 16 b3 3c  /..........X...<
 0020   89 1a a5 a2 af 3c 80 50 7b 99 71 05 3b 0e d3 27  .....<.P{.q.;..'
 0030   75 78 0d 0a 20 6c e7 1c ce 7b 5d 52 ad f1 04 88  ux.. l...{]R....
 0040   ec fa 04 c9 6a 74 fc 7b 3d 99 aa 8a ec 7a a3 18  ....jt.{=....z..
 0050   81 63 2f db b0 16 5b 49 63 f4 53 bc 57 18 27 37  .c/...[Ic.S.W.'7
 0060   f2 7f 66 e6 4d 46 59 2d 17 39 d5 79 a4 49 4d 93  ..f.MFY-.9.y.IM.
 0070   d2 80 34 8b 49 f5 31 72 7f 7b 41 46 37 9b ae a9  ..4.I.1r.{AF7...
 0080   3c f0 6f 2e 7f 75 e3 bf 2f d8 fc a4 be cb 2c 84  <.o..u../.....,.
 0090   01 b2 25 01 23 91 6e c0 c1 09 9d 42 c8 b8 e6 1b  ..%.#.n....B....
 00a0   fe 1e ed b3 52 7f 25 90 ae fc 34 f5 96 1b f0     ....R.%...4....

        16             Handshake protocol type
        03 01          SSL version (TLS 1.0)
        aa 04          Message length (170 bytes)

        04             New Session Ticket message type (extension)
        00 00 a6       Message length (166 bytes)
        00 .. f0       Session Ticket data


 ChangeCipherSpec message

 0000   14 03 01 00 01 01                                ......

        14             ChangeCipherSpec protocol type
        03 01          SSL version (TLS 1.0)
        00 01          Message length

        01             ChangeCipherSpec message


 Finished message (encrypted)

 0000   16 03 01 00 30 6d 09 0e 9f dd 09 03 2f 84 65 f8  ....0m....../.e.
 0010   94 0f d6 7b 4b 54 31 a1 25 a4 27 03 ae c3 4e af  ...{KT1.%.'...N.
 0020   27 04 32 5a 1f 29 90 fa 0a 4b 89 2f af d8 88 99  '.2Z.)...K./....
 0030   41 de dd 89 3f                                   A...?

        16             Handshake protocol type
        03 01          SSL version (TLS 1.0)
        00 30          Message length (48 bytes)

        6d .. 3f       Encrypted Finished message

(5)应用数据(客户端<->服务端)

此时,客户端和服务器已经完成了握手,加密通信也已经就绪,因此应用数据可以被安全地发送了。以下是示例的记录,单个TCP包可以携带多个报文:

 ApplicationData message

 0000   17 03 01 00 30 5d 15 3d a2 40 ef d2 01 25 ca 54  ....0].=.@...%.T
 0010   26 5f 5d b0 d2 2f 2f 6d 2d ec 56 85 b0 4c a9 bf  &_]..//m-.V..L..
 0020   eb 97 be 31 ad cd de 3a b4 71 1e c8 53 96 0b 2d  ...1...:.q..S..-
 0030   c3 91 3d a2 15                                   ..=..

        17             ApplicationData protocol type
        03 01          SSL version (TLS 1.0)
        00 30          Message length (48 bytes)

        5d .. 15       Encrypted application data

(6)关闭连接

因为我们已经处于加密连接中了,唯一能够真正知道在包内发送的是什么东西的方式,就是配置通信密钥,并使用Wireshark或者类似的工具。尽管可以这么做,我认为出于分析的目的,当连接被客户端或者服务端主动关闭连接的时候,只要客户端发送一个警告报文就够了。警告报文的类型应该是CloseNotify(type为0),但是我们从原始数据中是看不出来的。在这种情况下,客户端就是下列Alert报文的发送端:

 Alert message

 0000   15 03 01 00 20 3e 2e 43 30 49 49 6a f6 37 69 eb  .... >.C0IIj.7i.
 0010   0d dd c3 e2 d3 e1 5d e3 4e b3 e2 22 9d 85 f9 c4  ......].N.."....
 0020   59 b3 41 a9 86                                   Y.A..

        15             Alert protocol type
        03 01          SSL version (TLS 1.0)
        00 20          Message length (32 bytes)

        3e .. 86       Encrypted alert message


八、结论

就我目前为止从流量分析中看到的来说,标准库和客户端的实现都遵循了TLS 1.0规范。希望这篇文章能够帮助你了解SSL/TLS协议的一些内在工作机制。我发现检查十六进制的原始数据(特别是使用Wireshark这种强有力的工具)是一种非常有趣且有效的方式来了解网络的工作原理。


参考资料