nginx中session ticket重用Session提高https性能分析

原创文章:来自nginx中session ticket重用Session提高https性能分析

https会话建立初次使用session ticket的SSL握手流程如下:

     Client                                               Server

     ClientHello
    (empty SessionTicket extension)-------->
                                                     ServerHello
                                 (empty SessionTicket extension)
                                                    Certificate*
                                              ServerKeyExchange*
                                             CertificateRequest*
                                  <--------      ServerHelloDone
     Certificate*
     ClientKeyExchange
     CertificateVerify*
     [ChangeCipherSpec]
     Finished                     -------->
                                                NewSessionTicket
                                              [ChangeCipherSpec]
                                  <--------             Finished
     Application Data             <------->     Application Data

Figure 1: Message Flow for Full Handshake Issuing New Session Ticket

If the server successfully verifies the client's ticket, then it MAY renew the ticket by including a NewSessionTicket handshake message after the ServerHello in the abbreviated handshake. The client should start using the new ticket as soon as possible after it verifies the server's Finished message for new connections. Note that since the updated ticket is issued before the handshake completes, it is possible that the client may not put the new ticket into use before it initiates new connections. The server MUST NOT assume that the client actually received the updated ticket until it successfully verifies the client's Finished message.

而session重用时SSL握手简化为如下步骤:

   Client                                                Server
     ClientHello
     (SessionTicket extension)      -------->
                                                      ServerHello
                                  (empty SessionTicket extension)
                                                 NewSessionTicket
                                               [ChangeCipherSpec]
                                   <--------             Finished
     [ChangeCipherSpec]
     Finished                      -------->
     Application Data              <------->     Application Data

Figure 2: Message Flow for Abbreviated Handshake Using New Session
                              Ticket

使用session ticket机制可以提高ssl握手的效率,并节约有效的服务器计算资源.(另外一种是使用session cache)

nginx中使用 ssl_session_ticket_key file; 指令来配置用于加密或解密SSL session_ticket的密钥, 如果用了多个指令文件,则仅第一个指令文件中的密钥用来加密; 其它的密钥文件,并且第一个密钥文件都可以用做解密.

一般nginx.conf 中配置如下

ssl_session_ticket_key encode_decode.key;
ssl_session_ticket_key decode.key;

encode_decode.key用于加密ticket 也用于解密ticket

decode.key用于解密曾用decode.key加密过的ticket;

如果nginx.conf中没有配置key文件,则openssl默认会生成随机数的key,生成的时机: (keys are randomly generated when SSL context is initialized).

session ticket机制综述

The ticket mechanism is a TLS extension. The client can advertise its support by sending an empty “Session Ticket” extension in the “Client Hello” message. The server will answer with an empty “Session Ticket” extension in its “Server Hello” message if it supports it. If one of them does not support this extension, they can fallback to the session identifier mechanism built into SSL.

session tickets are an optional TLS extension and therefore, the support is not as widespread as for session identifiers. Support for tickets was added in OpenSSL 0.9.8f (October 2007)

TLS 和session ticket机制相关的RFC文档

  • TLS 1.0 defined in [RFC2246]
  • TLS 1.1 defined in [RFC4346]
  • TLS 1.2 defined in [RFC5246]
  • RFC5077 Transport Layer Security (TLS) Session Resumption without Server-Side State January 2008 目前用的是RFC5077,取代RFC4507
  • SessionTicket TLS [RFC4507] 被RFC5077取代
  • TLS扩展字段的规定 https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
  • Extensions: Extension Definitions [RFC6066]
  • 握手阶段最后一条由server发出的NewSessionTicket消息的格式(RFC 5077)如下, 可以是全握手时发出,也可以是简要握手时发出
NewSessionTicket消息的格式:
      struct {
          uint32 ticket_lifetime_hint;
          opaque ticket<0..2^16-1>;
      } NewSessionTicket;

ticket_lifetime_hint: The value indicates the lifetime in seconds as a 32-bit unsigned integer in network byte order relative to when the ticket is received.

RFC5077推荐的ticket消息格式如下:

The ticket is structured as follows:

      struct {
          opaque key_name[16];
          opaque iv[16];
          opaque encrypted_state<0..2^16-1>;
          opaque mac[32];
      } ticket;

followed by the length of the encrypted_state field (2 octets) and its contents (variable length).

上述结构encrypted_state未加密明文内容如下:

    struct {
          ProtocolVersion protocol_version;
          CipherSuite cipher_suite;
          CompressionMethod compression_method;
          opaque master_secret[48];
          ClientIdentity client_identity;
          uint32 timestamp;
      } StatePlaintext;

      enum {
         anonymous(0),
         certificate_based(1),
         psk(2)
     } ClientAuthenticationType;

      struct {
          ClientAuthenticationType client_authentication_type;
          select (ClientAuthenticationType) {
              case anonymous: struct {};
              case certificate_based:
                  ASN.1Cert certificate_list<0..2^24-1>;
              case psk:
                  opaque psk_identity<0..2^16-1>;   / from [RFC4279] /
          };
       } ClientIdentity;

注: 而在openssl 的实现中 session 共享的信息用结构体ssl_session_st来表示
或SSL_SESSION_ASN1, 使用i2d_SSL_SESSION()函数生成需要加密的ticket.

问题1 如果session ID 和session ticket都在client hello提供时以那个为准起作用?

答案: 以session ticket为准.详细的解释如下,

rfc5077 3.4. Interaction with TLS Session ID 做了说明如下:

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.

openssl代码中利用session ticket或session ID恢复session的处理实现逻辑:

ssl3_get_client_hello(SSL *s) -->
根据sessionID或ticket查找session的函数 ssl_get_prev_session()-->
根据ticket解密session信息tls1_process_ticket()-->
利用全局ctx ticket_key或应用层即nginx tlsext_ticket_key_cb回调解密 tls_decrypt_ticket()

如果上述解ticket失败或没有ticket则调用lh_SSL_SESSION_retrieve() 根据session id取cache中的信息恢复

如果openssl本身cache中没找到则根据session id从应用层nginx回调函数get_session_cb()中查找;并SSL_CTX_add_session(s->session_ctx, ret);//将外部的cache加入到openssl中

时间: 2024-08-20 11:18:33

nginx中session ticket重用Session提高https性能分析的相关文章

C#中使用反射的使用实现和性能分析

最近在研究一个可配置系统的框架,在代码中大量使用了反射的方法,虽然借鉴到其他的语言,如Java中反射性能都比较差,但是想到C#既然是一种强类型的语言,对于AppDomain中的类的调用应该性能不会差很多. 今天在mvp站点上看到有人说反射的性能很差,要避免使用,就写了一个简单的例子测试了一下 测试类如下: namespace ReflectionTest.Test { public class CTester { public CTester() { a = 10; } public void

Java中ArrayList和LinkedList的遍历与性能分析_java

前言 通过本文你可以了解List的五种遍历方式及各自性能和foreach及Iterator的实现,加深对ArrayList和LinkedList实现的了解.下面来一起看看吧. 一.List的五种遍历方式 1.for each循环 List<Integer> list = new ArrayList<Integer>(); for (Integer j : list) { // use j } 2.显示调用集合迭代器 List<Integer> list = new Ar

nginx反向代理tomcat,但是tomcat的程序中获取不到session?

问题描述 nginx反向代理tomcat,但是tomcat的程序中获取不到session? 浏览器打开nginx地址,代理到了tomcat,但是程序中却获取不到session,请问该如何配置.通过nginx访问就没有session 解决方案 http://blog.itpub.net/27043155/viewspace-733713/

Nginx中共享session会话配置方法例子_nginx

Session一般都指时域.在计算机术语中,Session是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入系统到注销退出系统之间所经过的时间以及如果需要的话,可能还有一定的操作空间. Session一般都指时域.在计算机术语中,Session是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入系统到注销退出系统之间所经过的时间以及如果需要的话,可能还有一定的操作空间. 通常情况下能把session改成cookie,就能避开session的一些弊端,在从前看的一本J2EE的

nginx中session跨页面失效问题如何解决

昨天在自己的服务器用session实现了一个登陆的功能,但是session跨页面不能使,着实捉急了一会.下面把解决过程记录下,防止下次遇到同样的问题又抓瞎了. 一般session失效的原因有以下几种: 1.浏览器COOKIE禁用. 2.服务器SESSION目录没有写权限. 先来看下服务器SESSION目录没有写权限的情况吧: 前提:这种情况的前提是你的session.save_handler=files,也就是文件存储session. 有的服务器用memcache存储session,可以看下是不

理解PHP中的Session及对Session有效期的控制_php技巧

0.什么是session?       Session的中文译名叫做"会话",其本来的含义是指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session.目前社会上对session的理解非常混乱:有时候我们可以看到这样的话"在一个浏览器会话期间,...",这里的会话是指从一个浏览器窗口打开到关闭这个期间:也可以看到"用户(客户端)在一次会话期间"这样一句话,它可能指用户的一系列动作(一般情况下是

javaweb-在ssh 中 用ServletActionContext获取session时启动报错

问题描述 在ssh 中 用ServletActionContext获取session时启动报错 ServletActionContext.getRequest().getSession(); 怎么才能在启动的时候就有ServletActionContext,而不用在ActionSupport处理请求时在获取 解决方案 是报空指针吗? 没有请求时 ServletActionContext.getRequest() 为null 解决方案二: http://blog.csdn.net/suncaoyo

php session 判断:php 5.4中新增加对session状态判断的功能

  在以前的php 版本中,要判断session是否有效,只能用如下的方法:session_start();if(isset($_session)){echo "started";}else{echo "not started";}   而在php 5.4(即将发行)中,对session的状态进行了细分,可以用如下的方法判断:session_start();$status = session_status();if($status == php_session_di

JSP中的page,request,session,application

application|js|request|session application和session比较简单,这里主要说明request和page的作用范围.application:全局作用范围,整个应用程序共享,就是在部署文件中的同一个webApp共享,生命周期为:应用程序启动到停止.session:会话作用域,当用户首次访问时,产生一个新的会话,以后服务器就可以记住这个会话状态.生命周期:会话超时,或者服务器端强制使会话失效.request:请求作用域,就是客户端的一次请求.page:一个J