昨天有位朋友在微信上发过来一个链接:The day Google Chrome disables HTTP/2 for nearly everyone: May 31st, 2016(中文翻译)。看标题这篇文章说的是 Google Chrome 即将大面积禁用 HTTP/2,这究竟是怎么回事呢?本文为你揭晓答案。
先来回顾一下,浏览器在访问 HTTPS 网站时,如何得知服务端是否支持 HTTP/2?答案是借助 HTTP/2 的协议协商机制:在 HTTP/2 Over HTTP 中,可以使用 HTTP 的 Upgrade 机制进行协商;而对于 HTTP/2 Over TLS,可以使用 TLS 的 NPN 或 ALPN 扩展来完成协商。HTTP/2 的这两种协商方式,不了解的同学请看《谈谈 HTTP/2 的协议协商机制》,这里不再赘述。
当前所有浏览器,都只支持 HTTP/2 Over TLS。也就是说,浏览器和服务端都支持 NPN 或 ALPN 协商,是用上 HTTP/2 的大前提。本文重点讨论 NPN 和 ALPN。
NPN(Next Protocol Negotiation,下一代协议协商),是一个 TLS 扩展,由 Google 在开发 SPDY 协议时提出。随着 SPDY 被 HTTP/2 取代,NPN 也被修订为 ALPN(Application Layer Protocol Negotiation,应用层协议协商)。二者目标一致,但实现细节不一样,相互不兼容。以下是它们主要差别:
大部分 Web Server 都依赖 OpenSSL 库提供 HTTPS 服务,对于它们来说,是否支持 NPN 或 ALPN 完全取决于使用的 OpenSSL 版本。通常,如果在编译时不特意指定 OpenSSL 目录,Web Server 会使用操作系统内置的 OpenSSL 库。
OpenSSL 1.0.2 才开始支持 ALPN,当前主流服务器操作系统基本都没有内置这个版本。以下是一份粗略的统计(via):
操作系统 内置 OpenSSL 版本
CentOS 5
0.9.8e
CentOS 6
1.0.1e
CentOS 7
1.0.1e
Ubuntu 14.04 LTS
1.0.1f
Ubuntu 16.04 LTS
1.0.2g
Debian 7 (Wheezy)
1.0.1e
Debian 8 (Jessie)
1.0.1k
这份表格列举的系统中,只有最近刚发布的 Ubuntu 16.04 才内置了支持 ALPN 的 OpenSSL 1.0.2。也就是说,直接使用系统 OpenSSL 库的 Web Server,极有可能不支持 ALPN 扩展。
去年,Google 在 Chrome 47 中移除了对 NPN 的支持,只支持 ALPN,但很快就引发一大批 HTTP/2 网站的抱怨。最终,Google 不得不在接下来的版本中又重新启用了 NPN。
半年后的今天,Google 又一次决定在 Chrome 51 中移除 NPN,预计 5 月底发布。这一次恐怕不会再反悔了。
本文开头那篇文章的作者悲观地认为:现在 OpenSSL 1.0.2 的普及程度仍然太低,Chrome 现在去掉对 NPN 的支持,仍然会导致一大批不支持 ALPN 的 HTTP/2 网站最终无法协商到 HTTP/2,只能降级使用 HTTP/1.1。
对此,我的观点是,该来的总会来,既然不能改变结果,不如早做准备。
通过 OpenSSL 命令行工具,可以快速查看自己的 HTTP/2 服务是否支持 ALPN 扩展:
openssl s_client -alpn h2 -servername imququ.com -connect imququ.com:443 <
/dev/null | grep 'ALPN'
如果提示 unknown option -alpn
,说明本地的 OpenSSL 版本太低(可通过 openssl version
查看),请升级到 1.0.2+。如果不方便升级,也可以使用 Qualys SSL Labs's SSL Server Test 这个在线工具来测试。
如果结果包含 ALPN protocol: h2
,说明服务端支持 ALPN,不受 Chrome 51+ 去掉 NPN 的影响。
如果结果包含 No ALPN negotiated
,说明服务端不支持 ALPN,在 Chrome 51+ 中无法协商到
HTTP/2,需要尽快升级。
由于 OpenSSL 是系统基础库,大量其他软件都对它有依赖,如果直接升级系统自带的 OpenSSL,很容易引发各种问题。更为稳妥的做法是在编译 Web
Server 时自己指定 OpenSSL 的位置。例如,我在《本博客 Nginx 配置之完整篇》这篇文章中提供的 Nginx 编译步骤中,就通过
\--with-openssl
指定了新版 OpenSSL 源码路径,这样编译出来的 Nginx 就会用上最新的 OpenSSL 库。
如果你在用 LibreSSL 做为 Web Server 的 SSL 库,需要升级到 2.1.3+ 才支持 ALPN。
OkHttp 是一个 Android 下比较常用的 HTTP 客户端,支持 HTTP 和 HTTP/2 协议。它在一年前也移除了对 NPN 的支持,所以支持 HTTP/2 但不支持 ALPN 的网站,在 OkHttp 客户端中会降级到 HTTP/1.1。
Chrome 51 这次也会彻底移除对 SPDY 的支持,如果你的网站还只支持 SPDY,趁这个机会直接升级到 HTTP/2 + ALPN 吧。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8