HTTPS 與 TLS 的真正運作原理:實用指南
為什麼 HTTPS 很重要(以及為什麼你應該了解它)
你大概看過瀏覽器裡的鎖頭圖示,也知道 HTTPS 會加密流量。但當出現憑證錯誤,或 API 呼叫因 TLS 錯誤而失敗時,你確切知道發生了什麼事嗎?許多開發者把 HTTPS 當成黑盒子——直到出問題為止。本指南將拆解 HTTPS 與 TLS 的實際運作方式,從握手到憑證鏈,讓你更有信心地除錯。
基礎概念:HTTPS = HTTP + TLS
HTTPS 就是將 HTTP layered 在 TLS(Transport Layer Security)之上。TLS 提供三項保證:
- 加密:資料經過編碼,竊聽者無法讀取。
- 認證:你正在與真正的伺服器通訊,而非冒充者。
- 完整性:資料在傳輸過程中若被修改,將被偵測到。
在 TLS 1.3 之前,該協定稱為 SSL(Secure Sockets Layer),但 SSL 已被棄用。如今,TLS 1.2 和 1.3 是標準。
TLS 握手:逐步解析
握手是魔法發生的地方。這是一段對話,在傳送任何 HTTP 資料之前建立安全通道。以下是 TLS 1.2 的簡化版本(TLS 1.3 更快,但概念類似):
- Client Hello:客戶端傳送支援的 TLS 版本、加密套件,以及一個隨機值(Client Random)。
- Server Hello:伺服器選擇 TLS 版本和加密套件,傳送自己的隨機值(Server Random),並出示其憑證。
- 憑證驗證:客戶端檢查憑證是否由受信任的根 CA 簽發、是否過期,以及網域名稱是否匹配。
- 金鑰交換:使用 ECDHE 等演算法,雙方在不透過網路傳送的情況下推導出共享密鑰(pre-master secret)。
- Finished:雙方驗證握手完整性,並切換到使用從共享密鑰衍生的對稱金鑰進行加密通訊。
在 TLS 1.3 中,握手減少為一個往返(1-RTT),甚至支援 0-RTT 用於恢復的會話,從而改善延遲。
為什麼非對稱加密只在一開始使用
非對稱加密(如 RSA 或 ECDSA)速度慢且運算成本高。TLS 僅用它來安全地交換對稱會話金鑰,之後便用該金鑰進行大量加密(例如 AES-GCM 或 ChaCha20-Poly1305)。這種混合方法平衡了安全性和效能。
憑證與信任鏈
憑證將公開金鑰綁定到網域名稱,並由憑證授權單位(CA)簽署。瀏覽器和作業系統內建受信任根 CA 的存放區。當伺服器出示其憑證時,客戶端會從伺服器憑證建立一條鏈,經過中繼 CA,最終到達受信任的根。
常見的憑證錯誤包括:
- 憑證過期:憑證的有效期限已結束。
- 主機名稱不符:憑證的主體別名(SAN)與請求的網域不符。
- 不受信任的簽發者:根 CA 不在客戶端的信任存放區中(例如自簽憑證)。
- 鏈不完整:伺服器未傳送中繼憑證,因此客戶端無法建立到受信任根的路徑。
像 openssl s_client 或線上 SSL 檢查工具可協助診斷這些問題。
除錯 HTTPS 連線
當 HTTPS 失敗時,你需要檢查握手。以下是一些實用指令:
# 檢查憑證詳細資訊和鏈
openssl s_client -connect example.com:443 -servername example.com -showcerts
# 驗證 TLS 版本和加密套件
openssl s_client -connect example.com:443 -tls1_3
# 測試憑證到期時間
openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
在瀏覽器中,開發者工具的安全面板會顯示連線詳細資訊,而 curl -v https://example.com 會揭露握手步驟。
常見的 TLS 錯誤配置
即使啟用了 HTTPS,錯誤配置仍可能削弱安全性或破壞相容性:
| 問題 | 影響 | 修正 |
|---|---|---|
| 啟用了弱加密套件 | 易受降級攻擊 | 停用 RC4、DES 和出口加密套件;偏好 AEAD 加密套件 |
| 缺少 HSTS 標頭 | 易受 SSL 剝離攻擊 | 新增 Strict-Transport-Security 標頭 |
| 憑證鏈不完整 | 部分客戶端出現錯誤 | 在伺服器配置中包含中繼憑證 |
| 允許舊版 TLS(1.0/1.1) | 合規性和安全風險 | 停用 TLS 1.0 和 1.1;強制使用 TLS 1.2+ |
如何在實務中檢查 TLS
如果你正在除錯網頁伺服器,首先檢查憑證鏈和加密套件。對於 Nginx,確保你的配置包含完整鏈:
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
使用 SSL Labs 等線上工具取得全面報告,但始終用命令列工具進行快速檢查。
常見問題
TLS 和 SSL 有什麼區別?
SSL 是 TLS 的前身。由於安全漏洞,SSL 2.0 和 3.0 版本已被棄用。TLS 1.2 和 1.3 是目前的安全協定。
為什麼我的瀏覽器顯示憑證警告,即使憑證是有效的?
常見原因包括憑證鏈不完整、主機名稱不符,或憑證由你的系統不信任的 CA 簽發。檢查憑證的 SAN 並確保提供中繼憑證。
如何檢查我的伺服器支援哪個 TLS 版本?
使用 openssl s_client -connect yourdomain.com:443 -tls1_3(或 -tls1_2),並在輸出中尋找協定。SSL Labs 等線上工具也提供詳細報告。
當你在除錯期間需要快速檢查或格式化 API 回應中的 JSON 資料時,JSON Formatter 可以幫助你視覺化並驗證結構。