NGINX 的 TLS 握手依赖 OpenSSL 实现,自身仅作配置驱动与终结点:接收 ClientHello(含 SNI),匹配 server 块并加载证书;响应 ServerHello、证书链等;完成密钥交换与 Finished 验证后加密传输 HTTP 数据,支持会话复用及 TLS 1.3 简化流程。

NGINX 作为反向代理或 Web 服务器,其 TLS 握手过程本质是遵循标准 TLS 协议(如 TLS 1.2 / TLS 1.3),并不自行实现密码学逻辑,而是依赖 OpenSSL(或 BoringSSL、OpenSSL 替代库)完成密钥交换与身份验证。理解握手流程,关键在于厘清 NGINX 在其中的角色——它既是 TLS 终结点(Terminator),也是配置驱动者。
Client_Hello:连接发起与能力通告
客户端(如浏览器)发起 HTTPS 请求时,首先发送 ClientHello 消息。该消息包含:
- TLS 版本(如 TLS 1.2 或 TLS 1.3)
- 客户端支持的密码套件列表(cipher suites),例如
ECDHE-ECDSA-AES256-GCM-SHA384 - 支持的椭圆曲线(如 x25519、secp256r1)和密钥交换参数
- 随机数(Client Random),用于后续密钥派生
- 可选扩展(SNI、ALPN、key_share 等)——其中 SNI(Server Name Indication)至关重要,NGINX 依靠它选择对应 server 块和证书
NGINX 在收到 ClientHello 后,根据 SNI 字段匹配 server_name,加载对应的 SSL 证书、私钥及配置(如 ssl_protocols、ssl_ciphers),为下一步响应做准备。
ServerHello 及证书链:服务端响应与身份证明
NGINX(通过 OpenSSL)从 ClientHello 中筛选出双方都支持的最高 TLS 版本、最优密码套件和曲线,并构造 ServerHello 回复,包含:
- 选定的 TLS 版本与密码套件
- 服务端随机数(Server Random)
- 协商后的扩展(如 ALPN 协议选择 http/1.1 或 h2)
紧接着发送:
-
Certificate:发送配置中指定的证书文件(
ssl_certificate),通常含叶证书 + 中间 CA 证书(不包含根证书);NGINX 不验证自身证书有效性,但要求证书私钥匹配且未过期 - ServerKeyExchange(TLS 1.2 及部分场景):若使用 DHE/ECDHE,发送临时公钥参数
- CertificateRequest(双向认证时启用):要求客户端提供证书
- ServerHelloDone(TLS 1.2)或直接进入密钥确认(TLS 1.3)
密钥交换与 Finished 验证:建立共享密钥
客户端收到证书后,验证证书链可信性(由系统或浏览器信任库完成,NGINX 不参与)、域名匹配(CN/SAN)、有效期等。验证通过后:
- 生成预主密钥(Pre-Master Secret,TLS 1.2)或基于 key_share 直接计算共享密钥(TLS 1.3)
- 用服务器证书中的公钥加密预主密钥(RSA 密钥交换),或通过 ECDHE 完成 DH 计算(更安全,前向保密)
- 发送 ClientKeyExchange(TLS 1.2)或 encrypted_extensions + certificate + finished(TLS 1.3)
NGINX 使用私钥解密(RSA)或本地私钥参与 DH 计算(ECDHE),结合 Client/Server Random,派生出主密钥(Master Secret)及后续会话密钥(用于加密、MAC、IV)。双方各自计算并发送 Finished 消息——这是首个用协商密钥加密的报文,包含对之前所有握手消息的 HMAC,用于验证完整性与密钥一致性。
应用数据加密传输:握手完成后的安全通道
当双方成功校验对方的 Finished 消息后,TLS 握手完成。此后:
- 所有 HTTP 请求/响应(如 GET /index.html)均被分帧、加密(AES-GCM)、添加认证标签,再封装为 TLS 记录(TLS Record)传输
- NGINX 在 TLS 层解密后,才将明文 HTTP 流量转发给上游(proxy_pass)或读取本地文件(root);反之,响应也先由 NGINX 加密再发往客户端
- 会话复用(Session ID / Session Ticket)可跳过完整握手:NGINX 通过
ssl_session_cache缓存会话参数,加速重复连接
注意:TLS 1.3 大幅简化流程,1-RTT 完成握手(甚至 0-RTT 支持早期数据),移除了 RSA 密钥传输、压缩、重协商等不安全特性,NGINX 1.13.0+ 通过 OpenSSL 1.1.1+ 支持 TLS 1.3,需显式启用 ssl_protocols TLSv1.3;。










