此前一篇文章用 wireshark 這個抓包工具除錯了一下 HTTP 請求和響應。詳細闡述了 TCP 連線和斷開的整個過程。這篇文章嘗試使用 wireshark 來抓取 TLS 封包,瞭解一下 HTTPS 請求和響應的整個過程。 ?
懶得看全文的直接拉到最下看 TLS 流程的圖片解釋
首先準備好 curl 和 wireshark,這些谷歌一下怎麼安裝。 ?
HTTPS 是基於 TLS 之上的,如果沒有目標的私鑰是沒辦法解密的,如果直接使用 wireshark 是看不到 TLS 層加密的資訊的。
開啟 wireshark 並開啟抓包,在 curl 中傳送一個請求:
再 wireshark 輸入 tls 過濾請求,疑似 ip 地址為目標網站
輸入該 ip 地址,確認是目標網站 httpbin,然後嘗試檢視返回的資料資訊,因為 TLS 加密是看不到返回的 JSON 資料的
因 TLS 使用的是迪菲 - 赫爾曼金鑰交換生成對稱金鑰的加密演算法,因此需要獲取到一系列生成金鑰的必要資訊後才可生成金鑰解密資料。
先不著急怎麼解決這個問題,首先回顧一下幾個知識點,大概瞭解一下加密演算法和 CA 數字證書和 TLS 加密流程:
必要的幾個知識點 ?
加密演算法 ?
遠古以前用的是對稱加密,這種加密和解密的金鑰是同一個,因此極為不安全,一旦其中一個金鑰洩露,那麼就會導致加密檔案被破解
後來發明了非對稱加密,這種加密方式的邏輯就是公鑰用來加密,私鑰用來解密,一方使用另一方的公鑰進行加密,傳輸密文給另一方,另一方再用私鑰進行解密,這樣沒有拿到私鑰就無法解密密文。但這種加密解密效率較低,後來就衍生出了混合加密,這種加密方式綜合了非對稱加密和對稱加密。
混合加密首先使用非對稱加密生成對稱金鑰,然後再使用對稱金鑰進行資料安全傳輸,這樣加密解密的效率要高得多了。TLS 用到的迪菲 - 赫爾曼就是其中的一種
關於迪菲 - 赫爾曼金鑰交換演算法,這裡簡單提一下,這種演算法有幾個特點:
- 金鑰可以合成但不能分解
- 合成後的金鑰可以繼續再合成
- 合成後的金鑰結果與合成順序無關
- 本質上是一種生成金鑰演算法
這個演算法的加密流程是這樣的:
- A 和 B 想要交換並生成對稱金鑰
- A 將 P 傳送給 B
- A 使用 P 和自己的私鑰 SA 合成 PSA
- B 使用 P 和自己的私鑰 SB 合成 PSB
- 雙方交換 PSA 和 PSB
- A 使用私鑰 SA 與 PSB 合成 PSBSA
- B 使用私鑰 SB 與 PSA 合成 PSASB
這樣對稱金鑰 PSASB 和 PSBSA 就合成完畢了,雙方就可以使用這個對稱金鑰對傳輸的資料進行加密 ?
⚠️ 問題是 A 將 P 傳送給 B,B 如何確認 P 就是真的來自 A 的呢,而不是受到中間人攻擊篡改了 P,這就需要使用 CA 認證了,只要有 CA 認證後的數字簽名並且通過 CA 的公鑰能夠驗證那麼就可以確認 P 就是來自 A 的。
數字證書 ?
因此這裡提一下 CA 證書也簡單提一下原理:
一個網站 A 想要獲取數字證書,那麼要走如下流程:
- A 將網站資訊和公鑰 PA 傳送給 CA 認證機構
- CA 認證機構驗證網站資訊並用自己的私鑰 SCA 加密生成數字簽名,並回傳給 A
- A 收到的數字簽名中就包含了 A 的公鑰 PA,那麼其他人只需要通過 CA 認證機構的公鑰即可認證解密數字簽名,獲取數字簽名中的公鑰 PA 了
- 那麼其他人就可以確定 PA 確實是來自 A 的
這樣 A 的公鑰 PA 就可以被認為確實是來自 A 的,因為有 CA 簽發的數字證書認證和背書。 ?
⚠️ 還有一個問題是 CA 的公鑰誰來認證呢?要是 CA 的公鑰也被惡意替換了怎麼辦?那麼就需要 CA 的 CA 來認證了,那麼 CA 的 CA 的公鑰誰來認證?根據這個邏輯,最後有一個 root CA,這個 CA 用來做最後的權威鑑定。
TLS 加密流程 ?
最後來回顧一下 TLS 的加密流程
TLS 是建立在 TCP 基礎上的,因此必定需要先三次 TCP 握手建立 TCP 連線,然後再是建立 TLS
- Client Hello
- Client Hello 報文:客戶端對加密演算法的支援度不同,因此需要向服務端傳送客戶端支援的 加密套件(Cipher Suite) ,同時還要生成一個 隨機數 同時儲存在客戶端和傳送給服務
- Server Hello
- ServerCertificate 報文:服務端收到 Client Hello 之後,向客戶端傳送 CA 認證的數字證書,用來鑑別服務端身份資訊,同時還要生成一個 隨機數 同時儲存在服務端和傳送給客戶端
- Server Hello Done 報文:表示服務端宣告第一階段的客戶端服務端握手協商結束
- 可選:Certificate Request 報文:必要情況下,要求客戶端傳送證書驗證身份
- 可選:Server Key Exchange 報文:如果 CA 認證的數字證書提供的資訊不夠,服務端還可傳送提供補充資訊
- Client Finish
- Client Key Exchange 報文:客戶端收到 CA 數字證書並通過驗證,然後通過 CA 公鑰解密獲取到 服務端公鑰。Client Key Exchange 報文包括有一個隨機數,這個隨機數被稱為 Pre-master key/secret;一個表示隨後的資訊使用雙方協商好的加密方法和金鑰傳送的 通知 ;還有一個通過協商好的 HASH 演算法對前面所有資訊內容的 HASH 計算值,用來提供服務端校驗。這些資訊都通過服務端公鑰加密傳送給服務端
- ClientCipherSpec 報文:該報文通知服務端,此後的通訊都將使用協商好的加密演算法計算對稱金鑰進行加密通訊(也就是使用兩個隨機數以及第三個 Pre-master key/secret 隨機數一起算出一個對稱金鑰 session key/secret)
- Finished 報文:該報文包括連線至此的所有報文的校驗值,使用服務端公鑰進行加密
- 可選:ClientCertificate 報文:如果服務端請求,客戶端需要傳送 CA 數字證書
- 可選:CertificateVerify 報文:服務端如果要求 CA 數字證書,那麼需要通過 HASH 演算法計算一個服務端傳送來的資訊摘要
- Server Finish
- 服務端最後對客戶端傳送過來的 Finished 報文使用服務端私鑰進行解密校驗
- ClientCipherSpec 報文:報文通知服務端,此後的通訊都將使用協商好的加密演算法計算對稱金鑰 session key/secret 進行加密通訊
- Finished 報文:標誌 TLS 連線建立成功
- TLS 握手成功此後通過對稱金鑰 session key/secret 加密通訊
以上,我們看到生成的兩個隨機數和 Pre-master key 一起計算生成 session key 就是通過上文中提到過的迪菲 - 赫爾曼金鑰交換演算法實現的。客戶端收到 CA 數字證書獲取到服務端公鑰進行加密,也符合上文中提到的 CA 認證流程。服務端私鑰解密客戶端使用服務端公鑰加密,在上文中的非對稱金鑰部分也進行了講解。因此 TLS 是一個運用到多種認證、加密的安全傳輸技術。除此之外,上文中沒有提到的使用 HASH 計算的目的則是為了防止資料遭到篡改,這跟我們大家在網上下載軟體,計算 md5 校驗是一個原理。
⚠️ 如有不正確的地方,各位請在評論區指正謝謝
最後抓包驗證上述加密流程 ?
首先上文提到過 wireshark 直接抓取 TLS 的封包是沒辦法看到解密後的資料的,那麼我們需要通過一些手段獲取到解密後的資料
那麼如何才能解密獲取資料呢,這裡有篇文章可以看看 jimshaver.net/2015/02/11/…
It turns out that Firefox and Chrome both support logging the symmetric session key used to encrypt TLS traffic to a file. You can then point Wireshark at said file and presto! decrypted TLS traffic.
原理是瀏覽器會在系統中存在名為 SSLKEYLOGFILE
的環境變數已經設定的情況下,將每個 HTTPS 連線產生的客戶端或服務端的隨機數、preMasterSecret、MasterSecret 全部獲取到並儲存在這個環境變數指定的檔案中。
配置環境變數 ?
開始動手實操,這裡用的是 windows 系統,我們配置環境變數:
配置完成,這樣瀏覽器就會寫入金鑰資訊到指定路徑的檔案中
至於 macOS/Linux 自己谷歌一下如何設定環境變數,很簡單不再贅述
配置 wireshark ?
開啟 wireshark,點選配置資訊指定 TLS 的 Pre-master key 路徑為環境變數指定的那個檔案路徑
這樣配置就算完成了,我們嘗試一下開啟 chrome 瀏覽器訪問一個 https 網址:
這裡訪問了百度的首頁,可以看到 wireshark 展現的已經是解密後的資料了
開始抓包分析 TLS 握手流程 ?
然後開啟終端使用 curl 傳送一個 https 請求
還是以 httpbin 為例,過濾 http 檢視 wireshark 的結果:
右鍵 follow 一下
這就是整個 TCP 建立到 TLS 握手再到 HTTP 請求響應以及 TCP 斷開的整個過程,我們逐一分析一下:
TCP 的此前文章已經說過了,這裡也不再提了,直接看 TLS 部分:
Client Hello
Client Hello 階段,客戶端給服務端傳送一個隨機數,以及 Cipher Suites 客戶端支援的所有加密套件
Server Hello
Server Hello 階段,服務端給客戶端傳送一個隨機數,以及選中的 Cipher Suite 加密套件
然後服務端繼續傳送給客戶端 CA 數字證書以及 Server Key Exchange 和 Hello done 資訊完成第一階段的握手:
這個是證書:
這個是 Server Key Exchange,可以看到協商了一種加密演算法:
這個是 Server Hello Done:
Client Finish
客戶端傳送一個 Client Key Exchange,Change Cipher Spec 和 Finished 報文
Finished Verify Data 包括至此連線的所有報文的校驗資訊,用服務端提供的公鑰加密
客戶端準備好切換為對稱金鑰加密
Server Finish
最後服務端返回一個 Change Cipher Spec 和 Server Finish
服務端準備好切換為對稱金鑰加密
TLS 握手成功
至此,TLS 握手成功,在 wireshark 中就可以看到接下來就是 HTTP 的請求響應封包了:
圖片解釋 ?
最後畫了個簡化版的腦圖方便理解:
⚠️ 如有不正確的地方,各位請在評論區指正謝謝
請關注我的訂閱號,不定期推送有關 JS 的技術文章,只談技術不談八卦 ?