文章目录
-
- 前情提要
- 前提說明
- [方法一:RSA 私鑰解密(僅適用 TLS 1.2,且 Cipher Suite 無 ECDHE/DHE)](#方法一:RSA 私鑰解密(僅適用 TLS 1.2,且 Cipher Suite 無 ECDHE/DHE))
- [方法二:SSLKEYLOGFILE(推薦,TLS 1.2 與 TLS 1.3 皆適用)](#方法二:SSLKEYLOGFILE(推薦,TLS 1.2 與 TLS 1.3 皆適用))
-
- [1. 設置環境變數](#1. 設置環境變數)
- [2. 依 Client 類型確認接入方式](#2. 依 Client 類型確認接入方式)
- [3. 抓包 + 產生流量](#3. 抓包 + 產生流量)
- [4. Wireshark 指向 keylog 檔案](#4. Wireshark 指向 keylog 檔案)
- [5. 驗證](#5. 驗證)
- 總結建議
前情提要
Wireshark will decrypt the TLS (HTTPS) traffic and save the plain text: 將TLS (https) decrypt 並保存明文
筆者現職開發 WiFi router/AP/bridge/local controller 產品,經常遇到各類傳輸throughput/traffic 問題,加上 cyber security 要求高漲的情況下,提供一種 debug 的方法
前提說明
| 項目 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 是否支援 RSA 靜態私鑰解密 | 支援(僅限 Cipher Suite 為 RSA key exchange,不含 ECDHE/DHE) | 不支援,協定已移除靜態 RSA 金鑰交換,憑證私鑰只用於簽章認證 |
| SSLKEYLOGFILE 是否適用 | 適用 | 適用(唯一可行方法) |
結論:若要一套方法同時涵蓋 TLS 1.2 與 TLS 1.3,應統一採用 SSLKEYLOGFILE。RSA 私鑰法僅作為 TLS 1.2 且未使用前向保密時的備選。
方法一:RSA 私鑰解密(僅適用 TLS 1.2,且 Cipher Suite 無 ECDHE/DHE)
- Wireshark → Edit → Preferences → Protocols → TLS
- 「RSA keys list」→ Edit → 新增一筆:
- IP address(伺服器 IP,可用
any) - Port(通常 443)
- Protocol(通常
http) - Key File(PEM 格式私鑰路徑,若有密碼則填入 Password)
- IP address(伺服器 IP,可用
- 抓包須包含完整 handshake(ClientHello ~ Certificate),Wireshark 會自動解密對應 Application Data,顯示在「Decrypted TLS」層。
限制 :Cipher Suite 名稱含 ECDHE/DHE 即代表前向保密,此法無效;TLS 1.3 一律無效。
方法二:SSLKEYLOGFILE(推薦,TLS 1.2 與 TLS 1.3 皆適用)
1. 設置環境變數
bash
export SSLKEYLOGFILE=/path/to/keylog.txt
需在啟動 client 進程之前設置,同一 shell/進程環境下執行。
2. 依 Client 類型確認接入方式
| Client | 是否原生支援環境變數 | 備註 |
|---|---|---|
| Chrome / Chromium / Edge | 是 | 易上手但系統笨重,設好變數直接啟動即可自動寫入 |
| Firefox | 是 | 同上 |
| curl(OpenSSL/BoringSSL/LibreSSL 編譯,7.61+) | 是 | 環境變數自動生效 |
OpenSSL s_client(1.1.1+) |
否,用參數 | openssl s_client -keylogfile keylog.txt ... 最推薦,openssl compile 可以比 curl 更加輕量化 |
| Python(3.8+) | 否,需程式碼設置 | ctx.keylog_filename = "/path/keylog.txt"(需自建 ssl.SSLContext,requests 需搭配 urllib3/httpx 自訂 adapter) |
| Node.js(12+) | 否,需程式碼設置 | 監聽 tlsSocket.on('keylog', line => fs.appendFileSync(path, line)) |
| Java(JSSE) | 否 | 需額外掛 Java agent(如 SSLKeyLogWriter)產生 |
| 自寫 C/C++(OpenSSL 1.1.1+) | 否 | 輕量化的極致。需呼叫 SSL_CTX_set_keylog_callback() 自行寫檔 |
3. 抓包 + 產生流量
先啟動 Wireshark 抓包(或 tcpdump/dumpcap),再執行 client 產生目標連線,抓包時間需涵蓋完整連線過程。
此時問題就變成如何將 sslkeylog 移動到 wireshark 的運行平台,畢竟比較不可能是使用 client 來運行
4. Wireshark 指向 keylog 檔案
Edit → Preferences → Protocols → TLS → 「(Pre)-Master-Secret log filename」→ 選擇 keylog.txt。
5. 驗證
打開對應 TCP 連線,Application Data 封包下應出現「Decrypted TLS」層並顯示明文(如 HTTP/2 請求回應)。
常見失敗原因:
- keylog 檔案沒有對應連線記錄(client 實際未寫入,常見於 Python/Node.js 未在程式碼中顯式設置)
- 抓包未包含 ClientHello 等握手起點封包
- Wireshark 版本過舊,不支援 TLS 1.3 解密(建議 3.0+)
總結建議
- 若目標流量可能含 TLS 1.3,直接採用 SSLKEYLOGFILE,不要依賴 RSA 私鑰法。
- RSA 私鑰法僅在舊系統、明確使用 RSA key exchange 且無法修改 client 時才考慮。
- Python / Node.js / Java 等語言需要額外修改程式碼或掛載 agent 才能產生 keylog,不能只靠設環境變數。