ALPN (应用层协议协商)
定义
ALPN 是一个 TLS 扩展,让客户端和服务器在握手过程中直接商定上层协议,例如 h2 或 http/1.1,不需要额外往返。
ALPN 由 RFC 7301 定义。客户端在 ClientHello 里列出自己支持的协议标识,如 h2、http/1.1,服务器从中选一个返回。TLS 1.3 中服务器的选择放在加密的 EncryptedExtensions 消息里,但客户端的候选列表仍在明文的 ClientHello 中。
为什么重要
浏览器只有在通过 ALPN 协商成功时才会使用 HTTP/2,否则自动退回 HTTP/1.1。所以“后端明明开了 HTTP/2,浏览器还是 1.1”的常见原因,是前面的反向代理或负载均衡没有通告 h2。基于 QUIC 的 HTTP/3 用的标识是 h3。ACME 的 TLS-ALPN-01 验证也建立在 ALPN 之上:CA 以 acme-tls/1 协议发起连接,服务器返回专门的验证证书,而不是平时的站点证书。按 RFC 7301,服务器一个候选协议都不支持时,应当以 no_application_protocol 告警中止握手,而不是等到 HTTP 层再出错。
例子
openssl s_client -connect example.com:443 -servername example.com -alpn h2,http/1.1 </dev/null 2>/dev/null | grep -i alpn
# ALPN protocol: h2
在 Nginx 中,较新版本用 http2 on;,旧版本用 listen 443 ssl http2; 开启 HTTP/2,对应的 ALPN 值就是 h2。
常见误区
- ALPN 用来协商 TLS 版本。 不是。TLS 版本和密码套件有各自的协商机制,ALPN 只决定 TLS 之上跑什么协议。
- ALPN 和 NPN 是一回事。 NPN 是早期由 Google 提出、由客户端选择协议的扩展,已被由服务器做选择的 ALPN 取代。
- 应用里开了 HTTP/2 就够了。 如果前面负责 TLS 终止 的代理没有通告
h2,客户端依然只会用 HTTP/1.1。