ssl_session_ticket_key仅支持单密钥(48字节二进制),而ssl_session_ticket_keys(1.19.4+)支持多密钥行(每行80字节:48字节AES+32字节HMAC),首行加密、全行解密,且reload可热重载。

必须轮转密钥,否则 ssl_session_tickets 实际等于“开盒即用”的安全隐患;但轮转本身不等于安全——密钥文件格式错、reload 失效、保留窗口不足,都会让轮转失效甚至导致复用中断。
ssl_session_ticket_key 和 ssl_session_ticket_keys 的区别在哪
两者不是版本迭代关系,而是功能分层:ssl_session_ticket_key 只能指定一个密钥文件(48 字节二进制),用于加密新票据和解密所有票据;ssl_session_ticket_keys 是 Nginx 1.19.4+ 引入的指令,支持按行加载多个密钥(每行 80 字节:48 字节 AES key + 32 字节 HMAC key),首行用于加密,全部行都可用于解密。
常见错误是把 ssl_session_ticket_key 写成多行配置,Nginx 会静默忽略第二行及之后的内容,导致旧票据无法解密。
- 生产环境应统一使用
ssl_session_ticket_keys(即使只配一把密钥),为后续轮转留出语法兼容性 - 密钥文件不可用文本编辑器手动修改或复制粘贴——
openssl rand 48 | xxd -p -c 48生成 hex 后,需用脚本转为 80 字节二进制格式(AES key + HMAC key) - 若用
ssl_session_ticket_key配多密钥(如旧文档所写),实际只生效第一个,且 reload 后旧密钥立即失效
密钥轮转后 nginx -s reload 为什么有时不生效
Nginx 在部分版本(尤其是 1.18.x 及更早)中,nginx -s reload 不会重新读取 ssl_session_ticket_key 或 ssl_session_ticket_keys 指令指向的密钥文件内容——它只重载配置语法,不重载已打开的文件句柄。这意味着即使你替换了密钥文件,worker 进程仍在用旧文件的内存映射。
- 验证方法:修改密钥文件后执行
lsof -p $(cat /var/run/nginx.pid) | grep ticket,看输出的 inode 是否变化 - 稳妥做法是
systemctl restart nginx或kill -TERM $(cat /var/run/nginx.pid) && nginx - Nginx ≥ 1.19.4 支持
ssl_session_ticket_keys的热重载,但前提是密钥文件路径不变、仅内容更新,且 reload 命令必须在主进程上下文中执行(非 sudo -u nobody)
如何设置密钥保留窗口才真正安全
TLS 票据本身没有显式过期时间,客户端依据服务器在 NewSessionTicket 消息中携带的 lifetime_hint 字段决定缓存时长(OpenSSL 默认约 4 小时)。但这个 hint 无法通过 Nginx 配置直接修改——它由底层 OpenSSL 库硬编码或编译时决定。
由 ReMe 驱动的记忆管理系统,支持跨会话记忆持久化、自动应用用户偏好以及智能上下文压缩...
所以“保留窗口”不是靠配置控制,而是靠密钥轮转节奏倒推:只要旧密钥还在 ssl_session_ticket_keys 列表里,对应 lifetime_hint 未过期的票据就仍可被解密。
- 建议轮转周期 ≤ 2 小时,密钥保留 ≥ 8 小时(覆盖 2 轮票据生命周期 + 服务重启/滚动发布延迟)
- 不要依赖
ssl_session_timeout控制票据有效期——它只影响ssl_session_cache,对 tickets 完全无效 - 可通过日志确认票据是否被成功复用:
$ssl_session_reused变量值为s(session ticket)或h(session id),配合 access_log 记录,比抓包更可靠
为什么不能只靠 session cache 而放弃 tickets
ssl_session_cache shared:SSL:10m 在单机上有效,但在多节点集群中,它要求所有机器共享同一块内存区域——这在物理隔离的服务器之间根本不可行。强行用 Redis 同步 session cache,会引入额外延迟、故障点和序列化开销,且无法解决跨机首次连接的全握手问题。
而 ssl_session_tickets 把状态交给客户端,服务端完全无状态。只要密钥一致,任意节点都能独立处理票据。它不是 session cache 的替代品,而是分布式场景下唯一可行的复用基础。
- 二者可共存:cache 优化同节点高频复用,tickets 解决跨节点复用
- 但若禁用
ssl_session_tickets,又没做 cache 共享,集群中超过 1/N 的请求(N 为节点数)将退化为全握手 - 密钥轮转失败时,最坏情况只是复用率下降,不会导致 TLS 握手失败——这点比 cache 溢出更可控
密钥轮转不是“设完 cron 就高枕无忧”的事。真正卡住人的,永远是那 48 字节是否真二进制、reload 是否真重载了文件、以及旧密钥删早了三小时——这些细节不验证,配置再漂亮也白搭。

















