TLS/SSL 协议详解

https://blog.csdn.net/mrpre/article/details/77868669

由于SSL握手的非对称运算无论是RSA还是ECDHE,都会消耗性能,故为了提高性能,对于之前已经进行过握手的SSL连接,尽可能减少握手round time trip以及运算。

SSL提供2中不同的会话复用机制。

1:session id会话复用

  对于已经建立的SSL会话,使用session id为key(session id来自第一次请求的server hello中的session id字段),主密钥为value组成一对键值,保存在本地,服务器和客户端都保存一份。

  当第二次握手时,客户端若想使用会话复用,则发起的client hello中session id会置上对应的值,服务器收到这个client hello,解析session id,查找本地是否有该session id,如果有,判断当前的加密套件和上个会话的加密套件是否一致,一致则允许使用会话复用,于是自己的server hello 中session id也置上和client hello中一样的值。然后计算对称秘钥,解析后续的操作。

  如果服务器未查到客户端的session id指定的会话(可能是会话已经老化),则会重新握手,session id要么重新计算(和client hello中session id不一样),要么置成0,这两个方式都会告诉客户端这次会话不进行会话复用。

报文分析

(1)这是一个全新的client hello请求,进行了full handshake。其实说全新的也不恰当,client hello中携带了session id,那是因为我之前访问过 10.30.0.1,而服务器没有进行会话复用时因为服务器会话老化了。故而本次连接是fullhandshake。

(2):服务器 回复的session  id 如下:

(3):握手完成之后,作为客户端,将dip dpot、 session id 和 master key关联起来。服务器也将session id

和master key关联起来,建立一个session挂链,等待后续使用。

(4):客户端再次发起请求,根据dip dport找到session id,然后添加到client hello 中:

显然,从报文行为上看得出,此次握手进行会话复用,服务器在本地链表中查找client hello 中session id,查找成功,则服务器的server hello中也携带了和客户端一样的session id以表明自己将要进行session id 会话复用,同时自己得到了session id对应的master key。

2:session ticket会话复用

     Session id会话复用有2个缺点,其一就是服务器会大量堆积会话,特别是在实际使用时,会话老化时间配置为数小时,这种情况对服务器内存占用非常高。

  其次,如果服务器是集群模式搭建,那么客户端和A各自保存的会话,在合B尝试会话复用时会失败(当然,你想用redis搭个集群存session id也行,就是太麻烦)。

Session ticket的工作流程如下:

1:客户端发起client hello,拓展中带上空的session ticket TLS,表明自己支持session ticket。

2:服务器在握手过程中,如果支持session ticket,则发送New session ticket类型的握手报文,其中包含了能够恢复包括主密钥在内的会话信息,当然,最简单的就是只发送master key。为了让中间人不可见,这个session ticket部分会进行编码、加密等操作。

3:客户端收到这个session ticket,就把当前的master key和这个ticket组成一对键值保存起来。服务器无需保存任何会话信息,客户端也无需知道session ticket具体表示什么。

4:当客户端尝试会话复用时,会在client hello的拓展中加上session ticket,然后服务器收到session ticket,回去进行解密、解码能相关操作,来恢复会话信息。如果能够恢复会话信息,那么久提取会话信息的主密钥进行后续的操作。

结合报文分析:

1:对于一个新的连接,客户端发若表明自己支持session ticket,则需要在client hello中携带session ticket拓展,并且里面为空。

2:若服务器也支持session ticket会话复用,则自己回复的sever hello中也需要带上session ticket拓展,表明自己后续将发送New session ticket,见上图最后一各报文。在change cipher spec前,服务器往客户端发送了session ticket。session ticket具体格式如下:

Lifetime Hint告知客户端session ticket老化时间,session ticket具体指由服务器计算,一般经过编码+加密流程,客户端无需知道具体内容。客户端收到后,将dip dport 与master key和 这个session ticket 关联起来。

3:客户端第二次发起请求,根据目的ip port查找,查找master key和session ticket,然后把session ticket加在client hello中的拓展中。同时也需要session id。

4:服务器收到这个client hello,解密session ticket,从中恢复master key,判断加密套件,协议等操作后,如果成功,则表示可以会话复用,服务器将按照会话复用流程,直接回复server hello,ccs,finished。

5:需要注意的是,客户端发起的client hello可能会携带session id,那么服务器若要表明自己此次session ticket复用成功,则回复的server hello也需要带上相同的session id。

RFC5077上这样描述:

   When presenting a ticket, the client MAY generate and include a
   Session ID in the TLS ClientHello.  If the server accepts the ticket
   and the Session ID is not empty, then it MUST respond with the same
   Session ID present in the ClientHello.  This allows the client to
   easily differentiate when the server is resuming a session from when
   it is falling back to a full handshake.  Since the client generates a
   Session ID, the server MUST NOT rely upon the Session ID having a
   particular value when validating the ticket.  If a ticket is
   presented by the client, the server MUST NOT attempt to use the
   Session ID in the ClientHello for stateful session resumption.
   Alternatively, the client MAY include an empty Session ID in the
   ClientHello.  In this case, the client ignores the Session ID sent in
   the ServerHello and determines if the server is resuming a session by
   the subsequent handshake messages.client MAY generate and include a
   Session ID in the TLS ClientHello.  If the server accepts the ticket
   and the Session ID is not empty, then it MUST respond with the same
   Session ID present in the ClientHello.  This allows the client to
   easily differentiate when the server is resuming a session from when
   it is falling back to a full handshake.  Since the client generates a
   Session ID, the server MUST NOT rely upon the Session ID having a
   particular value when validating the ticket.  If a ticket is
   presented by the client, the server MUST NOT attempt to use the
   Session ID in the ClientHello for stateful session resumption.
   Alternatively, the client MAY include an empty Session ID in the
   ClientHello.  In this case, the client ignores the Session ID sent in
   the ServerHello and determines if the server is resuming a session by
   the subsequent handshake messages.

猜你喜欢

转载自blog.csdn.net/moonpure/article/details/82979973