IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    为什么我们应该尽快支持 ALPN?

    JerryQu 的小站发表于 2016-05-18 22:58:52
    love 0

    昨天有位朋友在微信上发过来一个链接: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,当前主流服务器操作系统基本都没有内置这个版本。以下是一份粗略的统计:

    操作系统 内置 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。

    另外 Chrome 51 也会彻底移除对 SPDY 的支持,如果你的网站还只支持 SPDY,趁这个机会直接升级到 HTTP/2 + ALPN 吧。

    本文链接:https://imququ.com/post/enable-alpn-asap.html,参与讨论

    ♥ 本站所有文章均为本人原创,如果你认为我的文章对你有帮助,欢迎赞助本站。详情请点这里 »



沪ICP备19023445号-2号
友情链接