HTTPS 與 TLS 的實際運作原理:實用指南
為什麼 HTTPS 很重要,它到底做了什麼
你可能在瀏覽器上看過鎖頭圖示,並認為你的連線是安全的。但那個鎖頭到底保證了什麼?HTTPS(超文本傳輸安全協定)是建構在 TLS(傳輸層安全協定)之上的 HTTP。它提供三個核心保證:機密性(竊聽者無法讀取資料)、完整性(資料在傳輸過程中無法被修改而不被發現),以及驗證(你正在與真實的伺服器通訊,而不是冒充者)。
沒有 HTTPS,網路路徑上的任何人都可以讀取或篡改你的流量——無論是咖啡店的 Wi-Fi、你的 ISP,還是惡意的路由器。有了 HTTPS,這就變得不可行。但 TLS 不是魔法;它是一個精心設計的協定,有具體的步驟。了解這些步驟有助於你除錯連線問題、正確配置伺服器,並避免常見的陷阱。
TLS 握手:逐步解析
當你的瀏覽器連線到 HTTPS 網站時,它會在交換任何 HTTP 資料之前執行 TLS 握手。以下是典型的 TLS 1.3 握手(現代預設)中發生的情況:
- ClientHello:客戶端發送一條訊息,包含支援的 TLS 版本、密碼套件和一個隨機值(客戶端隨機數)。它還包括用於金鑰交換的金鑰共享(例如使用 ECDHE)。
- ServerHello:伺服器回應其選擇的 TLS 版本、密碼套件、一個隨機值(伺服器隨機數)以及自己的金鑰共享。它還發送其憑證鏈。
- 憑證驗證:客戶端根據受信任的根 CA 驗證伺服器的憑證,檢查主機名稱,並確保它未過期或未被撤銷。
- 金鑰衍生:雙方使用各自的私鑰和交換的金鑰共享計算出相同的共享密鑰。由此,他們衍生出對稱會話金鑰。
- Finished:雙方發送一條使用會話金鑰加密的 Finished 訊息,以驗證握手的完整性。
握手之後,所有應用程式資料(HTTP 請求和回應)都使用對稱會話金鑰加密。TLS 1.3 將握手減少到一個往返(1-RTT),並支援重複連線的 0-RTT 恢復,從而改善延遲。
憑證與信任鏈
憑證是將公鑰綁定到身分(如網域名稱)的數位文件。它由憑證授權單位(CA)簽署。你的瀏覽器和作業系統附帶了一個受信任根 CA 的存儲庫。當伺服器出示其憑證時,客戶端會從伺服器憑證向上構建一條鏈,直到受信任的根。如果任何環節缺失或無效,連線就會失敗。
常見的憑證問題包括:
- 憑證過期:有效期限已過。
- 主機名稱不符:憑證是為不同的網域簽發的(例如
example.com與www.example.com)。 - 鏈不完整:伺服器未發送中繼憑證,因此客戶端無法構建到受信任根的路徑。
- 不受信任的簽發者:憑證是自簽署的,或來自不在信任存儲庫中的 CA。
像 OpenSSL 這樣的工具可以幫助你檢查憑證。例如,要查看伺服器發送的憑證鏈:
openssl s_client -connect example.com:443 -showcerts
此命令會印出憑證和驗證結果。尋找 Verify return code: 0 (ok) 以確認鏈是有效的。
除錯 TLS 連線
當 HTTPS 失敗時,錯誤訊息通常會指出中斷的階段。以下是一個快速疑難排解表:
| 症狀 | 可能原因 | 動作 |
|---|---|---|
| 瀏覽器顯示「憑證已過期」 | 憑證已超過到期日 | 更新憑證並重新載入伺服器 |
| 「NET::ERR_CERT_COMMON_NAME_INVALID」 | 主機名稱不符 | 確保憑證涵蓋確切的網域(如有需要包括 www) |
| 「unable to get local issuer certificate」 | 缺少中繼憑證 | 配置伺服器發送完整的鏈 |
| 握手失敗並出現協定錯誤 | 客戶端和伺服器沒有共同的 TLS 版本或密碼套件 | 更新伺服器配置以支援現代 TLS(1.2+) |
如需更深入的檢查,請使用 openssl s_client 並加上 -tls1_3 等旗標來測試特定版本,或使用 curl -v https://example.com 查看握手詳細資訊。瀏覽器開發者工具(安全性標籤)也會顯示憑證資訊和連線詳細資訊。
伺服器配置的最佳實踐
正確的 TLS 配置對於安全性和效能至關重要。請遵循以下準則:
- 僅使用 TLS 1.3 和 1.2:停用較舊的版本(TLS 1.0、1.1),因為它們有已知的漏洞。
- 啟用 HTTP/2 或 HTTP/3:這些協定需要 TLS,並提供效能優勢。
- 使用強密碼套件:優先使用 AEAD 密碼,如 AES-GCM 或 ChaCha20-Poly1305。
- 啟用 OCSP 裝訂:減少延遲並改善撤銷檢查的隱私。
- 實作 HSTS:
Strict-Transport-Security標頭告訴瀏覽器始終對你的網域使用 HTTPS。 - 自動化憑證更新:使用 Let's Encrypt 搭配 Certbot 或類似工具,以避免過期。
以下是現代 TLS 的 Nginx 配置範例片段:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=63072000" always;
}
套用變更後,使用 SSL Labs 的 SSL Test(線上)或 openssl s_client 等工具測試你的配置,以驗證握手和憑證鏈。
常見問題
TLS 和 SSL 有什麼區別?
SSL(安全通訊端層)是 TLS 的前身。SSL 2.0 和 3.0 版本因安全缺陷而遭棄用。TLS 1.2 和 1.3 是現代、安全的協定。人們口語中常說「SSL」,但他們指的是 TLS。
HTTPS 如何防範中間人攻擊?
HTTPS 使用由受信任 CA 簽署的憑證來驗證伺服器。在握手期間,客戶端驗證伺服器的憑證,並檢查憑證中的公鑰是否與金鑰交換中使用的公鑰相符。這可以防止攻擊者在沒有有效憑證的情況下冒充伺服器。
我可以不使用憑證而使用 HTTPS 嗎?
不行。伺服器需要憑證來證明其身分,客戶端也需要憑證來建立加密通道。你可以使用自簽署憑證進行測試,但瀏覽器會顯示警告,因為它不受公共 CA 信任。對於生產環境,請使用來自受信任 CA(如 Let's Encrypt)的憑證。
在處理 TLS 配置時,你可能需要檢查伺服器日誌或測試端點。若要快速分析 Nginx 存取日誌以找出 TLS 錯誤或不尋常的模式,請試試 Nginx 日誌分析器,輕鬆解析和視覺化日誌資料。