大型網站的 HTTPS 實踐(4):協議層以外的實踐

ygw3 9年前發布 | 19K 次閱讀 HTTPS

1 前言

網上介紹 https 的文章并不多,更鮮有分享在大型互聯網站點部署 https 的實踐經驗,我們在考慮部署 https 時也有重重的疑惑。

本文為大家介紹百度 HTTPS 的實踐和一些權衡, 希望以此拋磚引玉。

2 協議層以外的實踐工作

2.1 全站覆蓋 https 的理由

很多剛接觸 https 的會思考,我是不是只要站點的主域名換了 https 就可以?答案是不行。

https 的目的就是保證傳輸過程的安全,如果只有主域名上了 https,但是主域名加載的資源,比如 js,css,圖片沒有上 https,會怎么樣?

從效果上來說,沒有達到保證網站傳輸過程安全的目的,因為你的 js,css,圖片仍然有被劫持的可能性,如果這些內容被篡改 / 嗅探了,那么 https 的意義就失去了。

瀏覽器在設計上早就考慮的這樣的情況,會有相應的提示。具體的實現依賴瀏覽器,例如地址欄鎖形標記從綠色變為黃色, 阻止這次請求,或者直接彈出非常影響用戶體驗的提示 (主要是 IE),用戶會感覺厭煩,疑惑和擔憂安全性。

 大型網站的 HTTPS 實踐(4):協議層以外的實踐

很多用戶看見這個鏈接會習慣性的點”是”,這樣非 https 的資源就被禁止加載了。非 ie 的瀏覽器很多也會阻止加載一些危害程度較高的非 https 資源(例如 js)。我們發現移動端瀏覽器的限制目前會略松一些。

所以這里要是沒做好,很多情況連網站的基本功能都沒法正常使用。

2.2 站點的區別

很多人剛接觸 https 的時候,覺得不就是部署證書,讓 webserver 支持 https 就行了嗎。

實際上對于不同的站點來說,https 的部署方式和難度有很大的區別。對于一個大型站點來說,讓 webserver 支持 https,以及對 webserver 在 https 協議特性上做一些優化,在遷移的工作比重上,可能只占到 20%-40%。

我們考慮下以下幾種情況下,部署 https 的方案。

2.2.1 簡單的個人站點

簡單的定義:資源只從本站的主域或者主域的子域名加載。

比如 axyz 的個人 blog,域名是 axyzblog.com。加載主域名下的 js 和圖片。

 大型網站的 HTTPS 實踐(4):協議層以外的實踐

這樣的站部署 https,在已有證書且 webserver 支持的情況下,只需要把主域名替換為 https 接入,然后把資源連接修改為 https:// 或者 //。

2.2.2 復雜的個人站點

復雜的定義:資源需要從外部域名加載。

 大型網站的 HTTPS 實踐(4):協議層以外的實踐

這樣就比較麻煩了,主域資源容易適配 https,在 cdn 上加載的資源還需要 cdn 服務商支持 https。目前各大 cdn 的服務商正在逐漸提供 https 的支持,需要遷移的朋友可以看看自己使用的 cdn 是否提供了這項能力。一些 cdn 會對 https 流量額外收費。

 大型網站的 HTTPS 實踐(4):協議層以外的實踐

Cdn 使用 https 常見的方案有:

1 網站主提供私鑰給 cdn,回源使用 http。

2 cdn 使用公共域名,公共的證書,這樣資源的域名就不能自定義了。回源使用 http。

3 僅提供動態加速,cdn 進行 tcp 代理,不緩存內容。

4 CloudFlare 提供了Keyless SSL的服務,能夠支持不愿意提供私鑰, 不想使用公共的域名和證書卻又需要使用 cdn 的站點了。

2.2.3 簡單的大型站點

簡單的定義: 資源只從本站的主域, 主域的子域,或者自建 / 可控的 cdn 域名加載,幾乎沒有第三方資源。如果網站本身的特性就如此,或愿意改造為這樣的類型,部署 https 就相對容易。Google 推ter 都是非常好的范例。優點:已經改成這樣的站點,替換 https 就比較容易。缺點:如果需要改造,那么要很大的決心,畢竟幾乎不能使用多樣化的第三方資源了。

2.2.4 復雜,訪問速度重要性稍低的大型站點

復雜的定義:從本站的非主域,或者第三方站點的域名有大量的第三方資源需要加載,多出現在一些平臺類,或者有復雜內容展現的的網站。

訪問速度要求:用戶停留時間長或者強需求,用戶對訪問速度的耐受程度較高。比如門戶,視頻,在線交易類(比如火車票 機票 商城)網站。

這樣的站點,可以努力推動所有相關域名升級為支持 https。我們用下圖舉例說明下這樣修改會導致一個網站的鏈接發生怎樣的改變。

 大型網站的 HTTPS 實踐(4):協議層以外的實踐

負責流量接入的團隊將可控的接入環境改造為 http 和 https 都支持,這樣前端工程的工作相對就少一些。大部分時候將鏈接從 http:// 替換為 // 即可. 在主域名是 https 的情況下,其它資源就能自動從 https 協議下加載。一些第三方資源怎么辦?一般來說只有兩種選擇,一遷移到自己的 cdn 或者 idc 吧,二強制要求第三方自己能支持 https。

以全站 https 接入的 非死book 舉例。第三方廠商想在 非死book 上線一個游戲。非死book:請提供 https 接入吧。第三方想:能賺錢啊,還是提供下 https 接入吧。所以,足夠強勢,有吸引力,合作方也有提供 https 的能力的話,這是完全可行的。如果你的平臺接入的都是一些個人開發者,而且還賺不到多少錢的情況下,這樣就行不通了。

優點:前端改動相對簡單,不容易出現 https 下還有 http 的資源問題。

缺點:通常這樣的實現下,用戶的訪問速度會變慢,比如從 2.5 秒變為 3 秒,如上述的理由,用戶還是能接受的。對第三方要求高。

2.2.5 復雜,訪問速度有嚴格要求的大型站點

復雜的定義:同上。

訪問速度要求:停留時間不長,用戶對訪問速度的心理預期較高。

但是如果用戶把網站當作工具使用,需要你很快給出響應的時候,這樣的實現就不好了。后續幾個部分我們介紹下這些優化的抉擇。

2.3 域名的選擇

域名對訪問速度的影響具有兩面性:域名多,域名解析和建立連接的時間就多;域名少,下載并發度又不夠。

https 下重建連接的時間成本比 http 更高,對于上面提到的簡單的大型站點, 可以用少量域名就能滿足需求,對于百度這樣富展現樣式較多的搜索引擎來說,頁面可能展示的資源種類太多。而不同類型的資源又是由不同的域名 (不同的產品 或者第三方產品) 提供的服務,換一個詞搜索就可能需要重新建立一些資源的 ssl 鏈接,會讓用戶感受到卡頓。

 大型網站的 HTTPS 實踐(4):協議層以外的實踐

如果將域名限制在有限的范圍,維持和這些域名的連接,合并一些數據,加上有 spdy,http2.0 來保證并發,是可以滿足我們的需求的。

2.4 連接復用

連接復用率可以分為 tcp 和 ssl 等不同的層面,需要分開進行分析和統計。

2.4.1 連接復用的意義

HTTP 協議 (RFC2616) 規定一個域名最多不能建立超過 2 個的 TCP 連接。但是隨著互聯網的發展,一張網頁的元素越來越多,傳輸內容越來越大,一個域名 2 個連接的限制已經遠遠不能滿足現在網頁加載速度的需求。

目前已經沒有瀏覽器遵守這個規定,各瀏覽器針對單域名建立的 TCP 連接數如下:

瀏覽器 連接數
Firefox 2 2
Firefox 3+ 6
Chrome 6
Ie10 8
IE8 6
Safari 5 6
Opera 12 6

表格 1 瀏覽器單域名建立的最大并發連接數

從上表看出,單個域名的連接數基本上是 6 個。所以只能通過增加域名的方式來增加并發連接數。在 HTTP 場景下,這樣的方式沒有什么問題。但是在 HTTPS 連接下,由于 TLS 連接建立的成本比較高,增加并發連接數本身就會帶來較大的延遲,所以對域名數需要一個謹慎的控制。

特別是 HTTP2 即將大規模應用,而 HTTP2 的最大特性就是多路復用,使用多個域名和多個連接無法有效發揮多路復用和壓縮的特性。

那 HTTPS 協議下,一張網頁到底該有多少域名呢?這個其實沒有定論,取決于網頁需要加載元素個數。

2.4.2 預建連接

既然從協議角度無法減少握手對速度的影響,那能不能提前建立連接,減少用戶可以感知的握手延遲呢?當然是可以的。思路就是預判當前用戶的下一個訪問 URL,提前建立連接,當用戶發起真實請求時,TCP 及 TLS 握手都已經完成,只需要在連接上發送應用層數據即可。

最簡單有效的方式就是在主域下對連接進行預建,可以通過請求一些靜態資源的方式。但是這樣還是不容易做到極致,因為使用哪個連接,并發多少還是瀏覽 器控制的。例如你對 a 域名請求一個圖片,瀏覽器建立了兩個連接,再請求一張圖片的時候,瀏覽器很大概率能夠復用連接,但是當 a 域名需要加載 10 個圖片的時候,瀏覽器很可能就會新建連接了。

2.4.3 Spdy 的影響

Spdy 對于連接復用率的提升非常有效,因為它能支持連接上的并發請求,所以瀏覽器會盡量在這個鏈接上保持復用。

2.4.4 其它

也可以嘗試一些其他發方法,讓瀏覽器在訪問你的網站之前就建立過 https 連接,這樣 session 能夠復用。HSTS 也能有效的減少跳轉時間,可惜對于復雜的網站來說,開啟需要考慮清楚很多問題。

2.5 優化的效果

從百度的優化經驗來看看,如果不開啟 HSTS,用戶在瀏覽器直接訪問主域名,再通過 302 跳轉到 HTTPS。增加的時間平均會有 400ms+,其中 302 跳轉和 ssl 握手的因素各占一半。但是對于后續的請求,我們做到了對絕大部分用戶幾乎無感知。

這 400ms+ 還有很多可以優化的空間,我們會持續優化用戶的體驗。

3 HTTPS 遷移遇到的一些常見問題。

3.1 傳遞 Referrer

我們可以把自己的網站替換為 https,但是一般的站點都有外鏈,要讓外鏈都 https 目前還不太現實。很多網站需要從 referrer 中判斷流量來源,因此對于搜索引擎這樣的網站來說,referer 的傳遞還是比較重要的。如果不做任何設置,你會發現在 https 站點中點擊外鏈并沒有將 referrer 帶入到 http 請求的頭部中(http://tools.ietf.org/html/rfc7231#section-5.5.2)。現代的瀏覽器可以用 meta 標簽來傳遞 refer。(http://w3c.github.io/webappsec/specs/referrer-policy)

<meta name=”referrer” content=”always”> 傳遞完整的 url

<meta name=”referrer” content=”origin”> 只傳遞站點,不包含路徑和參數等。

對于不支持 meta 傳遞 referrer 的瀏覽器,例如 IE8, 我們怎么辦呢?

可以采用再次跳轉的方法,既然 HTTPS 下不能給 HTTP 傳遞 referer,我們可以先從 HTTPS 訪問一個可控的 http 站點,把需要傳遞的內容放到這個 http 站點的 url 中,然后再跳轉到目標地址。

 大型網站的 HTTPS 實踐(4):協議層以外的實踐

3.2 form 提交

有時需要將 form 提交到第三方站點,而第三方站點又是 http 的地址,瀏覽器會有不安全的警告。可以和 referrer 的跳轉傳遞采取相似的邏輯。

但是這樣對 referer 和 form 等內容的方案,并不是完美的解決方法,因為這樣還是增加了不安全的因素(劫持,隱私泄露等 )。理想情況需要用戶升級符合最新規范的瀏覽器,以及推進更多的站點遷移至 https。

3.3 視頻播放

簡單來說,如果你使用 http 的協議來播放視頻,那么瀏覽器仍然會有不安全的提示。所以你有兩種選擇,1 讓視頻源提供 https。2 使用非 http 的協議,如 rtmp 協議。

3.4 用戶異常

在 https 遷移的過程中,也會有不少熱心的用戶向我們反饋遇到的各種問題。

常見的有以下的一些情況:

1 用戶的系統時間設置錯誤,導致提示證書過期。

2 用戶使用 fiddler 等代理進行調試,但是沒有添加這些軟件的根證書,導致提示證書非法。

3 用戶使用的 Dns 為公共 dns 或者跨網設置 dns,一些請求被運營商作為跨網流量攔截。

4 連通性有問題,我們發現一個小運營商的 https 失敗率奇高,又沒法聯系到他們,只能不對他們進行 https 的轉換。

5 慢。有時由于網絡環境的因素,用戶打開其他網站也慢,ping 哪個網站都要 500-2000ms。這時 https 自然也會很慢。

4 結束語

對于復雜的大型網站來說,HTTPS 的部署有很多工作要完成。

面對困難和挑戰,有充足的動力支持著我們前進:https 上線后,劫持等原因導致的用戶功能異常,隱私泄露的反饋大幅減少。

熱心的用戶經常會向我們反饋遇到的各種問題。在以前,有時即使我們確定了是劫持的問題,能夠解決問題的方法也非常有限。每當這種時候,自己總會產生一些無力感。

HTTPS 的全站部署,給我們提供了能解決大部分問題的選項。能讓一個做技術的人看到自己的努力解決了用戶的問題,這就是最棒的收獲。

HTTPS 沒有想像中難用和可怕,只是沒有經過優化。與大家共勉。

 本文由用戶 ygw3 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!