全站HTTPS困難點

【轉自:http://www.n-1.cn/179.html】

“全站HTTPs”儼然成了目前的熱門話題,很多網站都在摩拳擦掌要實行全站HTTPs。

一開始大家想得都很簡單,把證書購買了、配好了,相應的路徑改一改,就沒有問題。事實也確實如此,單個獨立站點的HTTPs改造是很容易的。一旦走向“全站”,才發現事情遠遠比想象的要複雜,全站意味着所有資源面對所有客戶端,涉及的因素異常多,網絡上又沒有太多資料,只能自己摸索。下面我簡單講講遇到的幾個問題,提供一些經驗給大家參考。

201706089781_415.jpg

HSTS

如果一個網站既提供了HTTP服務,又提供了HTTPs服務(在過渡期通常如此),怎樣引導用戶訪問HTTPs的站點呢?這就是HSTS(HTTP Strict Transport Security)的作用。通過Web服務器上的設置,在收到HTTP訪問請求時,返回的header裏帶有Strict-Transport-Security字段,告知瀏覽器必須使用HTTPs進行訪問。

但是,HSTS並不能避免首次跳轉時遇到的劫持。要徹底解決這個問題,可以申請加入Preload List(預加載列表)。

Preload List是由Google Chrome維護的“HTTPs站點列表”,Chrome, Firefox, Safari, Edge, IE 11均在使用。一旦瀏覽器發現要訪問的站點在Preload List上,默認就會發起HTTPs鏈接。這樣,就避免了HSTS的首次跳轉被劫持的隱患。

SSL卸載

通常的方案裏,HTTPs的加密傳輸只限於客戶端出發的公網階段,在內網的通訊流量仍然採用非加密的HTTP傳輸。這種“把加密流量轉換爲非加密流量”的過程,就是常說的SSL/TLS卸載(Offloading,以下簡稱“SSL卸載”)。

有一些公司會採用F5來做負載均衡,F5應付單純的L4和L7的流量是沒有問題的,但進行SSL卸載時性能往往會急劇降低,F5可以提供專門的加速卡來解決這個問題,但價格不便宜。所以,還需要專門環節來進行SSL卸載,常見的Nginx和HAProxy都可以執行這個任務。

2010年Intel出品的Westmere系列處理器之後,CPU支持AES-NI(Advanced Encryption Standard New Instructions)指令集,可以極大提高軟件進行SSL加解密的速度(通常的數據是5倍左右)。但是,單純採用CPU並不會直接享受這種好處,還需要對應的OpenSSL提供支持。想要知道自己的OpenSSL是否利用了AES-NI加速,可以用OpenSSL的命令行調試,加上-evp參數,測試速度是否有明顯變化即可。

# without EVP API

openssl speed aes-256-cbc

Doing aes-256 cbc for 3s on 16 size blocks: 14388425 aes-256 cbc's in 3.00s

# with EVP API

openssl speed -evp AES256

Doing aes-256-cbc for 3s on 16 size blocks: 71299827 aes-256-cbc's in 3.00s

客戶端證書

HTTP的服務是很好驗證的。一般來說,無論客戶端是瀏覽器,還是其它工具,還是程序代碼,同樣的行爲,結果都是相同的。所以只要一種客戶端驗證通過,基本就可以認爲這個服務是沒有問題的。HTTPs的站點則不是如此。

與HTTP不同,HTTPs的連接建立是需要進行證書驗證的,一定要從根證書開始形成完整的信任鏈條,連接纔可以建立成功。然而,瀏覽器、普通工具、程序類庫,它們所信任的根證書在管理上是互相獨立的。比如,與瀏覽器不同的是,C#信任的根證書在local machine store或者current user store中,Java信任的根證書在JDK安裝目錄下的cacerts目錄中,iOS和Android的證書管理又有不同。好在廠商一般都提供了非常詳細的說明,仔細閱讀即可。

因爲瀏覽器的證書在使用中又可以持續更新,用戶往往感知不到,如果“想當然”認爲瀏覽器驗證通過就萬事大吉,很可能會出問題。比如國內有不少網站使用WoSign簽發的證書,但老版本的JDK並不信任WoSign的根證書,用瀏覽器瀏覽沒問題的網站,程序就會報錯,除非手動導入證書。Android的信任列表是隨固件更新而更新的,4.2以後才內置WoSign的信任。因爲WoSign行爲不端,前幾天Firefox, Chrome, Safari等主流瀏覽器又取消了對它的信任,也就意味着WoSign證書有安全風險,所以已經內置WoSign根證書的程序也應當做對應的設置。

服務器端證書

還是上面的現象:用瀏覽器驗證沒有問題的HTTPs站點,用程序訪問就有問題。這是爲什麼?

在服務器上證書配置錯誤,只有最終證書,而缺少中級證書的情況,我見過幾次了。通常,最終證書裏包含了中級證書相關的信息,所以如果缺少中級證書,瀏覽器爲了建立證書鏈,會做一次耗時的操作來獲取中級證書,而且這一切都發生在HTTPs連接真正建立之前。更糟糕的是,不少瀏覽器爲了“表現更好”,會想辦法繞過這個問題。所以缺少中級證書的情況一直存在,一直不會被發現,而程序調用的速度總是上不去,甚至有一定機率報錯(我就遇到過這個詭異的問題)。

如果把證書鏈配置完全,還要注意證書鏈的大小。有一些網站的完整證書異乎尋常地大,達到若干kb甚至幾十kb,也就是說,在建立連接之前,就必須先傳輸這麼多的數據。如果做單純的PC網頁瀏覽,或許不會有問題。但對於移動端和程序調用來說,這就是一場災難。最好的辦法,是用OpenSSL配合WireShark之類的工具,自己動手來測試。如果你熟悉TCP相關的知識,往往可以得到更好的優化方案。

OCSP和CRL也不可忽略。這兩項技術用來保證撤回證書(讓證書失效)的有效性。如果你仔細觀察,會發現證書裏都指定了對應的OCSP或者CRL的URL,用來檢查證書是否失效。按道理說,在每次建立HTTPs連接時,都應當進行OCSP或CRL檢查。返回結果通常在1k左右,如果請求非常頻繁,這個因素也應當考慮。

SNI

大家都熟悉“虛擬主機”的概念,它可以讓多個域名對應到同一個IP,讓同一臺服務器服務多個站點。在HTTP時代,可以在header中通過host來指定需要訪問的域名,一切看起來都那麼完美。

但是在HTTPs時代,卻沒有這樣的好事,傳統的HTTPs服務很難讓多個域名對應到同一個IP。在進行到HTTP通訊之前,必須先建立驗證證書建立連接。如果一個IP上綁定了多個域名,這個階段服務器根本沒法知道請求對應的是哪個域名,無疑會造成極大的不便。

爲了解決這種問題,SNI(Server Name Identification)應運而生了。這種技術說起來複雜,大家可以把它簡單理解爲“建立SSL/TLS通訊時的host header”,這樣就解決了一個IP只能配單張證書的問題。

然而SNI的誕生歷史並不長,許多客戶端的支持都存在奇怪的問題。比如JDK7支持SNI,但是JDK8的支持又有bug。而且這種支持往往需要調用原生的API纔可以實現,Resteasy之類的類庫並不支持。如果對SNI的支持有問題,即便配置正確也可能無法建立連接,因爲服務端並不能識別此請求需要的證書。

CDN

CDN已經是業界流行的技術了,對稍微大一點的網站來說,沒有CDN幾乎是不可想象的。HTTP時代的CDN方案相當成熟,HTTPs的情況則不是如此。

要使用HTTPs的CDN服務,就要決定是否將證書交給CDN提供商。基於中國目前的商業信譽水平,把證書交給CDN提供商的風險不可不考慮。惡意揣測,別有用心的人一旦拿到證書,可以很方便地通過DNS劫持發起中間人攻擊,而完全不被感知到。

另外,HTTP時代大家都喜歡將資源分散到多個不同的域名,因爲建立連接的成本很低,而同一個域名的併發連接數有限。在HTTPs環境下,每次建立連接的成本高了很多,頻繁下載和驗證證書對移動設備和移動網絡影響很大(尤其是證書很大的情況)。如果域名非常分散,影響就更加顯著。所以在HTTPs時代,把域名收縮集中反而是更好的辦法。

內容及其它

因爲HTTPs的內容中無法引用HTTP的資源,所以應當保證網頁中資源文件的鏈接都是HTTPs的。遺留的許多系統很可能並不注意這些事情,資源都採用絕對地址的形式,這樣改起來工作量很大。如果要修改,最好一步到位,直接改成“協議相對URL”。

絕對地址URL:http://www.a.com/b.css

協議相對URL://www.a.com/b.css

這樣瀏覽器就可以根據當前的協議,自動生成資源的絕對地址,無論是HTTP還是HTTPs,都可以自由切換。

如果資源都是自有的,切換HTTPs就相對容易。如果存在外部,尤其是UGC的資源,切換到HTTPs就很麻煩。如果是超鏈接,通常採用專門的跳轉服務,也就是下面這樣:

https://link.my.com/target=www.you.com

如果是圖片這類資源,可以設定專門的程序將其抓取過來存放在自己的服務器上,再將地址替換掉即可。但是,這樣做很可能要自己承擔流量壓力,同時還要承擔惡意程序攻擊的風險。

如果是視頻、遊戲等富文本、交互複雜的資源,如果源站沒有提供HTTPs的服務,多半隻能忍痛割愛,放棄內嵌展現的形式了。

最後再補充兩點經驗:

如果真的決定上HTTPs,最好有個人把OpenSSL玩熟,否則很多問題會讓你摸不着頭腦,OpenSSL是很好的調試工具,很方便定位問題。

HTTPs能解決運營商內容劫持的問題,如果是DNS劫持,要不要抱着“吾與汝偕亡”的態度上HTTPs,需要慎重考慮,我知道不少網站是HTTP與HTTPs可以隨時切換的,進可攻,退可守。

發佈了47 篇原創文章 · 獲贊 21 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章