Https优化方案(服务端优化配置篇--重用Session)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/supertor/article/details/84849166

HTTPS的主要缺点是需要设置连接,每次新的TLS连续都需要握手,以便创建共享的加密密钥,这个握手过程在标准TCP的握手过程之上还需要两个额外的来回过程,用这样一个高延时的连接,在网站第一个字节传输之前需要三个来回就让人感觉这个网站有点慢。

TLS有几个特征可以用来消除额外的来回,比如重用一个会话session,两个标准会话重用机制是 session IDs (RFC
5246) 和 session tickets (RFC
5077),使用其中一个技术,一个客户端可以重用之前创建的会话,这个会话是之前和服务器进行握手成功的,这样可以减少一次来回过程。

基于SessionID的会话重用适合现代所有浏览器,FireFox和Chrome还支持 session
tickets,服务器端的支持也广泛使用,nginx, Apache, HAProxy, IIS等等都支持session ID
和session ticket。

Session ID重用

重用一个加密的会话是很容易,前提是客户端和服务器端都保存了会话key,通过每个连接给出的唯一标识,服务器知道一个进来的连接是否已经在之前创建过,如果服务器在会话中也已经有会话key,它就能重用。

Session ID需要服务器保存会话状态如会话key等,这样下次连接才能复用,这就需要服务器保存很多状态信息,耗费了大量内存。

Session ID共享复用在Apache中可以通过SSLSessionCache 配置,在nginx可以通过ssl_session_cache设置。

Session ticket重用

在会话ticket复用中,服务器不用为每个session保存状态,它用一个blob数据保存状态,然后将它发给客户端用来维护后来连接,会话ticket允许服务器将其存储状态委托给客户端,类似HTTP cookie一样。

一个会话ticket是一个加密的数据blob,其中包含需要重用的TLS连接信息,如会话key等,它一般是使用ticket key加密,因为ticket key服务器端也知道,在初始握手中服务器发送一个会话ticket到客户端,存储到客户端本地,当重用会话时,客户端发送会话ticket到服务器,服务器解密然后重用会话。

Session Ticket的安全考虑

会话ticket有潜在的安全问题,一些TLS加密组件如ECDHE-RSA-AES128-SHA256提供一个安全属性成为向前安全forward secrecy,如果黑客获得了服务器的证书私钥,他们也不能获得会话来破解。

使用TLS 会话ticket,偷窃了ticket key1后不会允许黑客来解密先前的会话,这是的ticket key非常有价值,为了保持向前安全forward secrecy, ticket key应该经常轮换。

会话ticket重用在Apache中可以用SSLTicketKeyDefault 配置,在nginx中使用ssl_session_tickets,它们都没有自动轮换ticket key的自动机制,只能通过重启apache nginx来重新加载或创建新的随机key。

负载平衡

使用负载平衡器时,这些复用技术会遇到挑战,对于一个服务器复用一个连接,它需要先前会话的key,如果先前会话在其他服务器上,新的服务器必须得到原来会话的key。

这个问题被CloudFlare 和 Twitter使用系统产生一个集中统一的key来解决,ticket key被一个集中的统一的服务器定期创建,安全地发给所有服务器,实现会话ticket共享需要你的架构有一个定制系统的抉择。

总结

降低创建一个连接的来回过程使得网站加载速度提高,对于使用HTTPS的网站,会话存储可以用于提高连接创建的速度,而正确的实现方式,才能让页面加载时间更漂亮的缩短,特别是在有负载平衡的场合 。

如果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中
具体操作教程https://blog.csdn.net/supertor/article/details/84849666

猜你喜欢

转载自blog.csdn.net/supertor/article/details/84849166