SSL连接恢复

SSL/TLS 连接断开后的两种恢复机制

问题

SSL 连接断开后如何恢复?为什么需要连接恢复机制?

解答

SSL/TLS 完整握手需要 2-RTT(往返时间),计算开销大。连接恢复机制可以跳过部分握手步骤,提升性能。

1. Session ID 恢复

服务器为每个会话分配唯一 ID,客户端重连时携带该 ID,服务器查找缓存恢复会话。

# 完整握手流程
Client                              Server
  |---- ClientHello ---------------->|
  |<--- ServerHello + Certificate ---|
  |<--- ServerKeyExchange -----------|
  |<--- ServerHelloDone -------------|
  |---- ClientKeyExchange ---------->|
  |---- ChangeCipherSpec ----------->|
  |---- Finished ------------------->|
  |<--- ChangeCipherSpec ------------|
  |<--- Finished --------------------|

# Session ID 恢复流程(1-RTT)
Client                              Server
  |---- ClientHello + SessionID ---->|
  |<--- ServerHello + SessionID -----|
  |<--- ChangeCipherSpec ------------|
  |<--- Finished --------------------|
  |---- ChangeCipherSpec ----------->|
  |---- Finished ------------------->|

Nginx 配置示例:

server {
    listen 443 ssl;
    
    # 启用 Session 缓存
    ssl_session_cache shared:SSL:10m;  # 10MB 共享缓存
    ssl_session_timeout 10m;            # 会话有效期 10 分钟
}

2. Session Ticket 恢复

服务器将会话状态加密后发给客户端保存,重连时客户端携带 Ticket,服务器解密恢复会话。

server {
    listen 443 ssl;
    
    # 启用 Session Ticket
    ssl_session_tickets on;
    ssl_session_ticket_key /path/to/ticket.key;  # 加密密钥
}

3. TLS 1.3 的 0-RTT 恢复

TLS 1.3 支持 0-RTT 恢复,首次请求就可以携带加密数据:

Client                              Server
  |---- ClientHello + EarlyData --->|  # 首包就带数据
  |<--- ServerHello + Finished -----|
  |---- Finished ------------------>|

Node.js 启用 0-RTT:

const tls = require('tls');
const fs = require('fs');

const server = tls.createServer({
  key: fs.readFileSync('server-key.pem'),
  cert: fs.readFileSync('server-cert.pem'),
  // TLS 1.3 默认启用,支持 0-RTT
  minVersion: 'TLSv1.3'
});

server.on('secureConnection', (socket) => {
  // 检查是否为恢复的会话
  if (socket.isSessionReused()) {
    console.log('Session resumed');
  }
});

server.listen(443);

两种方式对比

特性Session IDSession Ticket
状态存储服务器端客户端
服务器内存需要缓存无需缓存
分布式支持需要共享缓存只需共享密钥
安全性较高依赖密钥管理

关键点

  • Session ID 由服务器存储会话状态,需要内存缓存
  • Session Ticket 由客户端存储加密的会话状态,服务器无状态
  • 两种方式都能将握手从 2-RTT 降到 1-RTT
  • TLS 1.3 支持 0-RTT,但存在重放攻击风险,仅适用于幂等请求
  • 分布式环境下 Session Ticket 更易扩展,只需同步加密密钥