當前位置:
首頁 > 最新 > 深入淺出 HTTPS

深入淺出 HTTPS

Why HTTPS?

以訪問 google.com 為例,用上 HTTPS 後:

Identity:你能確定你是在跟 google.com 在對話,而不是其他偽裝成 google 的惡意網站

Confidentiality:通信過程中,雙方發送的內容都不會被人竊取、偷窺(eavesdropping)

Integrity:中間人無法修改你與 google.com 互相發送的數據(tampering)

HTTPS 可以解決的一些常見問題:

保證用戶的隱私數據(如密碼、信用卡等)不被中間人竊取

避免 ISP 向你的網站注入廣告等

瀏覽器中一些高級的 API,只能在 HTTPS 網站上使用,如 Geography、push notifications。HTTP2 要求有 HTTPS。


歷史

HTTPS 雖然叫 HTTP over SSL (Secure Sockets Layer),但是現在看到的都是 TLS 了。SSL 是 Netscape 在 90 年代中期發明的,但是 Netscape 衰落後 SSL 交給了 IETF,IETF 在 1999 年發布了 TLS,作為 SSL 的繼任者。現在(2018 年 1 月),TLS 1.2 是主流的版本,而 1.3 版本還在起草階段。


HTTPS 101

對於 HTTPS 的入門知識,HTTP: The Definitive Guide 的第 14 章提供了非常好的文字和插圖。

由於計算非對稱加密所消耗的 CPU 比對稱加密多得多,因此 HTTPS 選擇使用非對稱加密來建立通信密鑰,使用對稱加密來加密傳輸的數據。

簡單的描述即是:

客戶端跟伺服器,先用非對稱加密協商一個通信密鑰

非對稱加密過程,客戶端用伺服器證書中的公鑰來進行加解密

客戶端跟伺服器再用之前協商的密鑰,以對稱加密的形式傳輸 HTTP 數據

下面描述相對完整的過程。一個完整握手(full handshake)的時序圖如下:

ClientHello 時,client 告訴伺服器它支持的 TLS 版本、Cipher Suites、SNI(Server Name Indication,後面詳述)等信息

ServerHello 時,server 選擇一個 TLS 版本和 chiper suite,並發送證書給 client

ClientKeyExchange 時,client 校驗證書(看 hash、域名、過期時間等),然後隨機生成一個 pre-master key,用證書中的公鑰進行加密,發給 server。client 和 server 都可以根據這個 pre-master key 來生成一個 session key,用於加密 HTTP 流量

ChangeCipherSpec 時,client 和 server 互相表示,後面數據用 session key 進行對稱加密後傳輸

最後,兩邊開始傳輸加密的數據

值得注意的是,ChangeCipherSpec 之前的數據均是明文傳輸(比如 ClientHello 和 ServerHello)。

P.S. 我對密碼學沒有研究,關於各種 key 的描述可能有不準確。


TLS handshake

TLS 主要有兩種類型的 handshake:

DH

RSA

性能

由快至慢:

DH 握手,使用非 RSA 證書

RSA 握手(只能使用 RSA 證書)

DH 握手,使用 RSA 證書

例如 CluodFlare 用的就是非 RSA 證書,公鑰使用的是 ECDSA 演算法:

而 GitHub 使用的就是 RSA 證書:


RSA 握手,會使用同一對公私鑰來做 authentication 和加密對稱密鑰(key establishment)。這使得一旦有攻擊者,在中間把兩端通信的流量截取下來,同時又獲得了伺服器的私鑰,則通信雙方的信息會全部被破解。這種加密方式無法保證 forward secrecy。

而 DH(Diffie-Hellman)握手時,可以實現 authentication 用 server 的公私鑰,但是 key establishment 用另外生成的一個 key。它能保證 forward secrecy。


RSA 握手的 cipher suites,如 TLS_RSA_WITH_AES_128_GCM_SHA256,表示:

RSA for key establishment

RSA for authentication

128-bit Advanced Encryption Standard in Cipher Block Chaining (CBC) mode for confidentiality

256-bit Secure Hashing Algorithm (SHA) for integrity

DH 握手的有 ECDHE-ECDSA-AES256-GCM-SHA384,表示:

Elliptic Curve Diffie-Hellman Ephemeral (ECDHE) key exchange for key establishment

Elliptic Curve Digital Signature Algorithms (ECDSA) for authentication

256-bit Advanced Encryption Standard in Galois/Counter mode (GCM) for confidentiality

384-bit Secure Hashing Algorithm for integrity

目前瀏覽器和主流的 server 端配置,會更傾向於使用 DH 握手。

用 WireShark 觀察瀏覽器發出的 TLS 握手信息,可以它支持的 cipher suites 及其優先順序。


Chain of Trust

Client 發起 TLS handshake 時,怎樣判斷 server 不是中間人扮演的呢?比如你訪問 google.com,怎樣判斷你是在跟真的 google.com 對話,而不是一個偽裝的呢?答案在證書中。

證書由 CA(Certificate Authority,數字證書認證機構)頒發。而 CA 又分 intermediate CA 和 root CA,一般網站的證書由 intermediate CA 頒發,而 intermediate CA 的證書則由根證書頒發。root CA 的證書則是自已頒發給自己(self-sign):

其中 Google Internet Authority 是 intermediate CA,GlobalSign 則是 root CA。

「頒發」這個動作,用的是電子簽名技術。比如 CA 頒發證書給你的網站,即是用 CA 的私鑰加密一段信息放進證書中。客戶端拿到證書後用 CA 的公鑰進行解密和校驗,則可以判斷證書是否真的是 CA 所頒發。而 root CA 的公鑰會被各操作系統、瀏覽器內置並且信任。如果你信任你的操作系統、瀏覽器中綁定的 root CA 信息,那麼你也會信任其簽名的 intermediate CA 證書和隨後的網站證書。這就是信任鏈的運作模式。

為了提升性能,server 發送證書給 client 時,會把證書路徑下的多個證書一起發給客戶端做校驗。

證書所使用的標準是 X.509 Version 3。


ALPN extension

TLS 只是一層加密層,它承載的應用數據可以是各種各樣,不僅限於 HTTP。ALPN (Application-Layer Protocol Negotiation) 是 client 用來與 server 協商通信層協議的。Client 在 ClientHello 發送它所支持的應用層協議(目前主要是 HTTP2 和 HTTP 1.1),server 從中選擇一個,通過 ServerHello 給回。

下面是用 WireShark 抓包的一個例子。ClientHello 中,Chrome 表示它接受 HTTP2 和 HTTP 1.1:

ServerHello 中,server 表示它選擇了 HTTP2:

SNI

SNI (Server Name Indication) ,是一個 TLS Extension,在 ClientHello 中可以看到它的身影:

由於 TLS 握手發生在實際的 HTTP 請求之前,web server 還無法通過 HTTP 頭中的 Host 欄位來判斷用戶訪問的是哪個網站,因此需要通過 TLS 協議帶過去。對於一個 IP 部署多個網站的情況,不同的網站往往使用不同的證書,web server 需要通過 SNI 它才可以判斷給哪個證書。

但是 SNI 和證書信息都是明文的,會導致中間人知道你訪問的是哪個網站。但是它無法知道你訪問網站裡面的什麼路徑、內容。


TLS Performance Tuning

TLS 性能調優這塊,強烈推薦看看 High Performance Browser Networking 的Transport Layer Security (TLS),寫得深入淺出、形象生動。我這裡是消化後的二手內容。


除去 TCP 三次握手,一個完整的 TLS 握手需要耗 2 個 RTT。TLS 握手主要是 client 跟 server 互相交換加密相關信息,而前一次協商後的結果往往可以用到下一次連接中,因此 TLS 提供了一些機制來降低這裡的延時。

第一種機制是,服務端提供一個 session ID 給客戶端,並緩存相應的握手信息。客戶端下一次連接握手時帶上 session ID,如果服務端查到該 ID 的相關握手信息,則可以省去一個完整的 session negotiation,直接用上次的對稱密鑰做通信。這樣節省掉 1 個 RTT:

Session ID 的問題是,現代大規模的網站往往前面有多機做負載均衡,比如多台 nginx 在前端做 TLS 相關的工作,再把請求轉發到後端邏輯 server。這樣導致 Session ID 的緩存需要能被多台 nginx 訪問,帶來了額外的運維成本。於是 TLS 給出第二種機制,session ticket,用來解決這個問題。

Session ticket 其實很簡單,就是把服務端緩存挪到客戶端。Session negotiation 的結果通過伺服器下發,然後客戶端緩存起來。下一次請求時客戶端又帶給伺服器,如果伺服器無異議,則可以直接開始數據傳輸。


TLS False Start 是 Google 提出來的一項優化,用來減少 TLS 握手的時延。原理是 client 發送 CipherChangeSpec 後立刻發送應用層數據:

TLS False Start 需要瀏覽器跟 server 都支持,比如:

協商的 cipher suite 需要支持 forward secrecy(因為不需要交換 pre-master key?)

雙方需要支持 ALPN Extention 而不是 NPN(參考:為什麼我們應該儘快支持 ALPN?)

Session Resumption 使得第二次 TLS 握手可以只用 1 個 RTT,但是第一次握手還是需要 2 個 RTT。而 TLS False Start 則使第一次 TLS 握手也只需要佔用 1 個 TLS。


證書在一些情況下會被 CA 吊銷,比如私鑰泄漏,證書更換主體等。這個時候需要有一種機制,讓客戶端不再信任已被吊銷的證書。

有幾種機制:

Certificate Revocation List (CRL),即 CA 維護一個龐大的已被回收的證書列表,由客戶端定時更新

Online Certificate Status Protocol (OCSP),即 CA 提供一個服務,讓客戶端可以實時查某個證書的吊銷情況

OCSP Stamping,下面詳述

前兩種存在的問題,可以自行考慮,這裡也給出了一些看法。

OCSP Stamping 是由 server 定時向 CA 發起 OCSP 請求,並附在 ServerHello 回給客戶端,而不是由客戶端發起。CA 給的 OCSP 回包會用它的私鑰加密,這樣 client 拿到這份 OCSP 回包時,可以校驗出是 CA 給的。這樣有幾個好處 client 不直接發 OCSP 給 CA,不會暴露訪問歷史,不需要自己等待 CA 給回復。

在 WireShark 觀察的相關數據如下:


前端相關

Jerry Qu 的博客上提到很多跟前端相關的 HTTPS 內容。前端內容多且繁雜,不同瀏覽器支持能力不一,在這裡就不詳述了,只簡單講講 HSTS 頭。


這個重定向帶來了額外的網路延時。可以用(HSTS) 頭,告訴瀏覽器應該只訪問這個網站的 HTTPS 版本。瀏覽器會忽略在 HTTP 頁面下收到的這個文件頭,因為攻擊者可以竄改這些數據。

HSTS 頭同樣可以解決一些安全問題。比如你在公共 Wi-Fi 中連接到一個攻擊者的熱點,你打開 HTTP 版本的網銀頁面時,攻擊者會把頁面 302 重定向到一個假的克隆的站點,以盜取密碼。如果網銀頁面啟用了 HSTS 頭,而且你之前訪問過它,那麼你在公共 Wi-Fi 中連接時,也會默認走 HTTPS,避開攻擊者的攻擊。

Chrome 維護了一個 HSTS preload list,即在這個名單中的域名,Chrome 會默認使用 HTTPS。Firefox 和 IE 似乎也使用這個列表。注意這個 preload list 並不在 HSTS 規範中,只是個事實上(de-facto)的規範。


安全

這塊我沒有深入了解,參考下Mozilla Wiki和RFC 7457 - Summarizing Known Attacks on Transport Layer Security (TLS) and Datagram TLS (DTLS)。


工具

Qualys SSL Labs能檢測不同瀏覽器 / Server 對於 SSL 的支持能力、安全性等,信息非常詳細

Mozilla 提供了非常好的工具,用來檢查一個網站支持的 cipher suites、證書路徑等:

mozilla/tls-observatory

mozilla/cipherscan

Mozilla 同時提供了一個SSL Configuration Generator,用來為不同的 web server 生成安全可靠的配置文件。

Is TLS Fast Yet?網站,提供了各伺服器程序(如 nginx)和 CDN 服務(如 Akamai)對 TLS 各優化項的支持能力。

Let"s Encrypt提供了免費的證書申請渠道和工具,工具可以幫你自動申請證書及修改 web server 配置,非常贊。


參考信息

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 onlyice 的精彩文章:

TAG:onlyice |