❗ 本文最后更新于 3038 天前,文中所描述的信息可能已发生改变,请谨慎使用。
昨天有位朋友在微信上发过来一个链接: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,应用层协议协商)。二者目标一致,但实现细节不一样,相互不兼容。以下是它们主要差别:
- NPN 是服务端发送所支持的 HTTP 协议列表,由客户端选择;而 ALPN 是客户端发送所支持的 HTTP 协议列表,由服务端选择;
- NPN 的协商结果是在 Change Cipher Spec 之后加密发送给服务端;而 ALPN 的协商结果是通过 Server Hello 明文发给客户端;
大部分 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 吧。
本文链接:https://imququ.com/post/enable-alpn-asap.html,参与评论 »
--EOF--
发表于 2016-05-18 22:58:52,并被添加「HTTP/2、Chrome、HTTPS、ALPN」标签。查看本文 Markdown 版本 »
专题「HTTP/2 相关」的其他文章 »
- 谈谈 Nginx 的 HTTP/2 POST Bug (Aug 20, 2016)
- 谈谈 HTTP/2 的协议协商机制 (Apr 14, 2016)
- 使用 nghttp2 调试 HTTP/2 流量 (Mar 07, 2016)
- 从启用 HTTP/2 导致网站无法访问说起 (Jan 17, 2016)
- 基于 HTTP/2 的 WEB 内网穿透实现 (Nov 23, 2015)
- HTTP/2:新的机遇与挑战 (Nov 22, 2015)
- HTTP/2 头部压缩技术介绍 (Oct 25, 2015)
- 使用 Wireshark 调试 HTTP/2 流量 (Oct 24, 2015)
- H2O 中的 Cache-Aware Server Push 简介 (Oct 21, 2015)
- HTTP/2 资料汇总 (Aug 31, 2015)
Comments
Waline 评论加载中...