為什麼我們應該盡快支持ALPN?

昨天有位朋友在微信上發過來一個鏈接: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吧。

Google Chrome 很快要大面积禁用 HTTP/2,这究竟是怎么一回事呢?本文为你揭晓答案。

來源: 为什么我们应该尽快支持 ALPN? | JerryQu 的小站

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。