03-4. HTTPS 握手過程

⏱️ 閱讀時間: 15 分鐘 🎯 難度: ⭐⭐⭐ (中等)


🎯 本篇重點

深入理解 HTTPS 握手的完整流程、TLS 1.2 和 TLS 1.3 的差異、握手過程中的每個步驟細節,以及如何優化握手效能。


🤔 什麼是 HTTPS 握手?

TLS Handshake = 建立安全連線前的「協商過程」

一句話解釋: HTTPS 握手就像是兩個人見面前先確認身份、交換密碼本、約定暗號,確保之後的對話只有彼此能聽懂。


🤝 用見面交換情報來比喻握手

特務接頭

場景:兩個特務要交換機密情報

步驟 1:確認身份(憑證驗證)
特務A:報上名來
特務B:我是特務B,這是我的證件 🎫(憑證)
特務A:檢查證件...✅ 確認是真的

步驟 2:交換密碼本(金鑰交換)
特務A:產生一本密碼本 📖
特務A:用特務B的公開加密箱鎖住密碼本
特務B:用私人鑰匙打開加密箱
→ 雙方都有相同的密碼本了

步驟 3:開始加密通訊(對稱加密)
特務A:用密碼本加密情報
特務B:用密碼本解密情報
→ 旁人聽不懂

特性:
- 確認身份(防止冒充)
- 安全交換密碼本(防止竊聽)
- 加密通訊(防止洩密)

🔄 完整的 HTTPS 連線流程

概覽

【第 1 步:TCP 三次握手】
建立 TCP 連線(80 毫秒)

【第 2 步:TLS 握手】
建立安全連線(100-200 毫秒)

【第 3 步:HTTP 請求/回應】
加密的 HTTP 通訊

【第 4 步:關閉連線】
TCP 四次揮手 or Keep-Alive

總延遲:
TCP (1-RTT) + TLS (1-2 RTT) + HTTP (1-RTT)
= 3-4 RTT ≈ 200-400ms

📋 TLS 1.2 握手流程(詳細版)

完整流程(2-RTT)

客戶端                                    伺服器

【第 1 次往返(1-RTT)】

ClientHello ─────────────────────→
- TLS 版本:TLS 1.2
- 隨機數(Random_C)
- 支援的加密套件清單:
  - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  - ...
- 支援的壓縮方法
- 擴充欄位(SNI、ALPN)

                         ←───────── ServerHello
                         - 選擇的 TLS 版本:TLS 1.2
                         - 隨機數(Random_S)
                         - 選擇的加密套件
                         - 選擇的壓縮方法

                         ←───────── Certificate
                         - 伺服器憑證鏈 📜
                         - 網站憑證 + 中繼 CA 憑證

                         ←───────── ServerKeyExchange
                         - 金鑰交換參數
                         - ECDHE 公鑰
                         - 簽章(證明公鑰真實性)

                         ←───────── ServerHelloDone
                         - 伺服器訊息結束

【客戶端驗證】
1. 驗證憑證有效性 ✅
2. 檢查憑證鏈 ✅
3. 驗證簽章 ✅

【第 2 次往返(2-RTT)】

ClientKeyExchange ────────────────→
- ECDHE 公鑰
- 用伺服器公鑰加密的預主密鑰

ChangeCipherSpec ─────────────────→
- 通知切換到加密模式

Finished ─────────────────────────→
- 加密的握手訊息摘要
- 驗證握手過程完整性

                         ←───────── ChangeCipherSpec
                         - 伺服器切換到加密模式

                         ←───────── Finished
                         - 加密的握手訊息摘要

【握手完成】✅
雙方計算出「主密鑰」(Master Secret)
Random_C + Random_S + 預主密鑰 → 主密鑰

【開始加密通訊】
Application Data ←────────────────→
- 所有後續 HTTP 通訊都加密

詳細步驟解析

1️⃣ ClientHello

內容:
- TLS Version: TLS 1.2
- Random: [32 bytes random data]
  - 時間戳 (4 bytes)
  - 隨機數 (28 bytes)
- Session ID: (恢復會話用)
- Cipher Suites: (支援的加密套件)
  - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  - ...
- Compression Methods: null
- Extensions:
  - server_name (SNI): www.example.com
  - supported_groups: x25519, secp256r1, secp384r1
  - signature_algorithms: rsa_pss_rsae_sha256, ecdsa_secp256r1_sha256
  - application_layer_protocol_negotiation (ALPN): h2, http/1.1

作用:
- 告訴伺服器客戶端支援的功能
- 包含隨機數(防重放攻擊)

2️⃣ ServerHello

內容:
- TLS Version: TLS 1.2
- Random: [32 bytes random data]
- Session ID: [session id]
- Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (選擇的套件)
- Compression Method: null

作用:
- 確認使用的 TLS 版本
- 選擇加密套件
- 提供伺服器隨機數

3️⃣ Certificate

內容:
憑證鏈:
- 網站憑證(www.example.com)
- 中繼 CA 憑證
- (可選)根 CA 憑證

作用:
- 證明伺服器身份
- 提供公鑰用於後續加密

4️⃣ ServerKeyExchange

內容(ECDHE):
- Curve Type: named_curve
- Named Curve: x25519
- Public Key: [ECDHE public key]
- Signature Algorithm: rsa_pss_rsae_sha256
- Signature: [RSA signature]

作用:
- 提供 ECDHE 臨時公鑰
- 用憑證私鑰簽署(證明公鑰真實性)

5️⃣ ClientKeyExchange

內容(ECDHE):
- Public Key: [ECDHE public key from client]

作用:
- 提供客戶端 ECDHE 公鑰
- 雙方計算共享密鑰(Pre-Master Secret)

計算:
客戶端:client_private_key + server_public_key → shared_secret
伺服器:server_private_key + client_public_key → shared_secret
→ 相同的 shared_secret!

6️⃣ ChangeCipherSpec

內容:
- 單一訊息:0x01

作用:
- 通知對方:後續訊息都將加密

7️⃣ Finished

內容:
- verify_data: PRF(master_secret, "finished", Hash(handshake_messages))

作用:
- 驗證握手過程完整性
- 確認雙方計算出相同的密鑰
- 第一個加密的訊息

🚀 TLS 1.3 握手流程(簡化版)

完整流程(1-RTT)

客戶端                                    伺服器

【第 1 次往返(1-RTT)】

ClientHello ─────────────────────→
- TLS 版本:TLS 1.3
- 隨機數(Random_C)
- 支援的加密套件清單
- Key Share(直接包含公鑰)← 新增!
  - x25519: [client public key]
- 支援的簽章演算法
- SNI

                         ←───────── ServerHello
                         - TLS 版本:TLS 1.3
                         - 隨機數(Random_S)
                         - 選擇的加密套件
                         - Key Share(伺服器公鑰)

                         ←───────── EncryptedExtensions
                         (以下訊息都加密)

                         ←───────── Certificate
                         - 伺服器憑證

                         ←───────── CertificateVerify
                         - 憑證簽章驗證

                         ←───────── Finished
                         - 握手完成訊息

【客戶端驗證憑證】

Finished ─────────────────────────→
- 握手完成訊息

【握手完成】✅

Application Data ←────────────────→
- 開始加密通訊

改進:
✅ 只需 1-RTT(TLS 1.2 需要 2-RTT)
✅ 握手訊息大多加密(只有 ClientHello/ServerHello 明文)
✅ 強制前向保密(只支援 ECDHE)
✅ 移除不安全的加密套件

TLS 1.3 的關鍵改進

1. 1-RTT(更快)

TLS 1.2(2-RTT):
ClientHello →
            ← ServerHello + Certificate + ...
ClientKeyExchange + Finished →
            ← Finished
開始通訊

TLS 1.3(1-RTT):
ClientHello + KeyShare →
            ← ServerHello + KeyShare + Certificate + Finished
Finished →
開始通訊

時間差:
TLS 1.2:2 × RTT ≈ 200ms
TLS 1.3:1 × RTT ≈ 100ms
→ 快 100ms

2. 0-RTT(更更快)

TLS 1.3 支援 0-RTT 恢復會話:

第一次連線:
(正常 1-RTT 握手)
伺服器 → 客戶端:Session Ticket

第二次連線(同一伺服器):
ClientHello + Early Data →
(不等握手完成,直接發送 HTTP 請求)

→ 完全沒有額外延遲!

注意:
0-RTT 有重放攻擊風險
只適合冪等操作(GET)
不適合 POST/PUT/DELETE

3. 加密握手訊息

TLS 1.2:
大部分握手訊息明文
→ 可能洩露敏感資訊(SNI、ALPN)

TLS 1.3:
從 ServerHello 之後都加密
→ 只有 ClientHello/ServerHello 明文
→ 更好的隱私保護

4. 簡化加密套件

TLS 1.2:
支援數十種加密套件
包含許多不安全的選項
例:
- TLS_RSA_WITH_AES_128_CBC_SHA(不支援前向保密)
- TLS_RSA_WITH_RC4_128_SHA(RC4 不安全)

TLS 1.3:
只支援 5 種安全套件
強制前向保密(ECDHE)
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
- TLS_AES_128_CCM_SHA256
- TLS_AES_128_CCM_8_SHA256

→ 移除所有不安全的選項

🔍 關鍵概念詳解

隨機數(Random)的作用

為什麼需要隨機數?

1. 防止重放攻擊(Replay Attack)
駭客:記錄完整的握手過程
駭客:重新發送相同的訊息
→ 如果沒有隨機數,會產生相同的密鑰
→ 駭客可以解密

有隨機數:
每次握手的隨機數都不同
→ 每次產生不同的密鑰
→ 重放攻擊無效

2. 增加熵(Entropy)
Random_C + Random_S → 更隨機的密鑰

產生主密鑰:
Master Secret = PRF(
    Pre-Master Secret,
    "master secret",
    Random_C + Random_S
)

PRF(偽隨機函數)

PRF = Pseudo-Random Function

作用:
從少量秘密(Pre-Master Secret)
產生大量密鑰材料

TLS 1.2 PRF:
基於 HMAC-SHA256

用途:
從 Pre-Master Secret 產生:
1. Master Secret
2. Client Write Key(客戶端加密密鑰)
3. Server Write Key(伺服器加密密鑰)
4. Client Write IV(初始向量)
5. Server Write IV
6. Client Write MAC Key
7. Server Write MAC Key

→ 一個秘密衍生出所有需要的密鑰

SNI(Server Name Indication)

問題:
一個 IP 位址可能有多個網站
TCP 連線時還不知道要訪問哪個網站
伺服器不知道要提供哪個憑證

範例:
伺服器 IP: 192.168.1.100
├─ www.example1.com
├─ www.example2.com
└─ www.example3.com

客戶端連線到 192.168.1.100
伺服器:不知道要提供哪個憑證?

SNI 解決方案:
ClientHello 包含 SNI 擴充:
server_name: www.example1.com

伺服器:
收到 SNI → 知道是 www.example1.com
→ 提供對應的憑證

缺點:
SNI 是明文(TLS 1.2)
→ ISP 可以看到你訪問的網站
→ 隱私問題

TLS 1.3 改進:
Encrypted SNI (ESNI)
→ 加密 SNI,保護隱私

ALPN(Application-Layer Protocol Negotiation)

作用:
協商應用層協定

ClientHello:
ALPN: h2, http/1.1

ServerHello:
ALPN: h2

→ 雙方同意使用 HTTP/2

好處:
- 避免額外的協商往返
- 在 TLS 握手中完成
- 支援 HTTP/2、HTTP/3

⚡ 握手效能優化

1. Session Resumption(會話恢復)

問題:
每次連線都要完整握手
→ 耗時

解決:
第一次連線:完整握手 + Session ID

伺服器 → 客戶端:Session ID: abc123

第二次連線:
ClientHello + Session ID: abc123 →
                         ← ServerHello + Session ID: abc123
                         ← ChangeCipherSpec + Finished
Finished →
開始通訊

縮短為:1-RTT(省略憑證傳輸和金鑰交換)

TLS 1.2:Session ID 或 Session Ticket
TLS 1.3:Session Ticket(PSK)

2. OCSP Stapling

問題:
驗證憑證是否被撤銷
客戶端 → OCSP 伺服器:查詢憑證狀態
→ 增加延遲(額外的 DNS + TCP + HTTP 請求)

OCSP Stapling 解決:
伺服器定期從 OCSP 伺服器取得憑證狀態
伺服器 → 客戶端:憑證 + OCSP 回應

優點:
✅ 不需要額外請求
✅ 更快(省略 OCSP 查詢)
✅ 更好的隱私(客戶端不直接聯繫 OCSP)

Nginx 設定:
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/chain.pem;

3. TLS False Start

作用:
客戶端在收到 Finished 前就開始發送應用資料

TLS 1.2:
ClientKeyExchange + Finished + HTTP Request →
(不等伺服器 Finished)

省略:0.5 RTT

要求:
- 必須是強加密套件
- 必須支援前向保密(ECDHE)
- TLS 1.2+

TLS 1.3:
已內建(握手訊息和應用資料可以同時發送)

4. HTTP/2 Server Push

作用:
伺服器主動推送資源

傳統:
1. 客戶端:GET /index.html
2. 伺服器:<html>... <link rel="stylesheet" href="style.css">
3. 客戶端:解析 HTML → 發現需要 style.css
4. 客戶端:GET /style.css
5. 伺服器:返回 style.css

HTTP/2 Server Push:
1. 客戶端:GET /index.html
2. 伺服器:
   - 推送:style.css
   - 推送:script.js
   - 返回:index.html

省略:多次往返

🛠️ 實際觀察握手過程

使用 Wireshark

步驟:
1. 打開 Wireshark
2. 選擇網路介面
3. 過濾器:ssl or tls
4. 訪問 https://www.google.com
5. 查看封包

可以看到:
├─ Client Hello
├─ Server Hello
├─ Certificate
├─ Server Key Exchange
├─ Server Hello Done
├─ Client Key Exchange
├─ Change Cipher Spec
├─ Encrypted Handshake Message
└─ Application Data (加密的 HTTP)

使用 OpenSSL

# 查看握手過程
openssl s_client -connect www.google.com:443 -state

# 輸出:
SSL_connect:before SSL initialization
SSL_connect:SSLv3/TLS write client hello
SSL_connect:SSLv3/TLS read server hello
SSL_connect:SSLv3/TLS read server certificate
SSL_connect:SSLv3/TLS read server key exchange
SSL_connect:SSLv3/TLS read server done
SSL_connect:SSLv3/TLS write client key exchange
SSL_connect:SSLv3/TLS write change cipher spec
SSL_connect:SSLv3/TLS write finished
SSL_connect:SSLv3/TLS read change cipher spec
SSL_connect:SSLv3/TLS read finished

# 查看握手時間
time openssl s_client -connect www.google.com:443 < /dev/null

# 測試特定 TLS 版本
openssl s_client -connect www.google.com:443 -tls1_2
openssl s_client -connect www.google.com:443 -tls1_3

使用 curl

# 顯示詳細資訊
curl -v https://www.google.com

# 輸出:
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384

# 測試特定 TLS 版本
curl --tlsv1.2 https://www.google.com
curl --tlsv1.3 https://www.google.com

# 顯示時間統計
curl -w "@curl-format.txt" -o /dev/null -s https://www.google.com

# curl-format.txt:
    time_namelookup:  %{time_namelookup}\n
       time_connect:  %{time_connect}\n
    time_appconnect:  %{time_appconnect}\n
      time_redirect:  %{time_redirect}\n
   time_pretransfer:  %{time_pretransfer}\n
 time_starttransfer:  %{time_starttransfer}\n
                    ----------\n
         time_total:  %{time_total}\n

🎓 面試常見問題

Q1:TLS 1.2 和 TLS 1.3 握手有什麼差異?

A:TLS 1.3 更快、更安全

主要差異:

1. 往返次數(RTT)
TLS 1.2:2-RTT
ClientHello →
            ← ServerHello + Certificate + ...
ClientKeyExchange + Finished →
            ← Finished
開始通訊(4 個訊息往返)

TLS 1.3:1-RTT
ClientHello + KeyShare →
            ← ServerHello + KeyShare + Certificate + Finished
Finished →
開始通訊(2 個訊息往返)

→ TLS 1.3 快一倍

2. 0-RTT(更快)
TLS 1.3 支援 0-RTT 恢復會話
→ 完全沒有額外延遲
→ 但有重放攻擊風險

3. 加密握手訊息
TLS 1.2:大部分握手訊息明文
TLS 1.3:握手訊息加密(除了 ClientHello/ServerHello)
→ 更好的隱私保護

4. 前向保密
TLS 1.2:可選(DHE/ECDHE)
TLS 1.3:強制(只支援 ECDHE)
→ 即使私鑰洩露,過去的通訊仍安全

5. 簡化加密套件
TLS 1.2:數十種加密套件(有些不安全)
TLS 1.3:只有 5 種安全套件
→ 移除所有不安全的選項

效能提升:
TLS 1.2:約 200ms
TLS 1.3:約 100ms
→ 快 100ms

結論:
✅ TLS 1.3 更快(1-RTT vs 2-RTT)
✅ TLS 1.3 更安全(強制前向保密)
✅ TLS 1.3 更簡單(更少選項)
✅ 建議使用 TLS 1.3

Q2:握手過程中客戶端如何驗證憑證?

A:檢查五個方面

驗證流程:

1. 檢查憑證有效期
檢查:
- Not Before:憑證生效時間
- Not After:憑證過期時間

當前時間:2025-01-06
憑證有效期:2024-01-01 to 2026-01-01
→ 在有效期內 ✅

2. 檢查憑證網域名稱
檢查:
- Common Name (CN)
- Subject Alternative Name (SAN)

訪問:www.example.com
憑證 CN:www.example.com ✅
或
憑證 SAN:www.example.com, example.com ✅

3. 檢查憑證鏈(Chain of Trust)
網站憑證:www.example.com
    ↓ 由誰簽發?
中繼 CA:Let's Encrypt Authority X3
    ↓ 由誰簽發?
根 CA:ISRG Root X1
    ↓ 在瀏覽器信任清單中?
✅ 信任

4. 驗證數位簽章
CA 用私鑰簽署憑證
瀏覽器用 CA 公鑰驗證簽章
→ 簽章有效 ✅
→ 憑證未被篡改

5. 檢查憑證是否被撤銷
方法 1:CRL(Certificate Revocation List)
- 下載撤銷清單
- 檢查憑證序號是否在清單中

方法 2:OCSP(Online Certificate Status Protocol)
- 即時查詢憑證狀態
- 更快但需要額外請求

方法 3:OCSP Stapling
- 伺服器提供 OCSP 回應
- 不需要額外請求

全部通過:
✅ 憑證有效
🔒 顯示安全連線

任一失敗:
❌ 憑證無效
⚠️ 顯示警告

Q3:什麼是前向保密(Perfect Forward Secrecy)?

A:即使私鑰洩露,過去的通訊仍然安全

傳統方式(RSA 金鑰交換):
1. 客戶端產生 Pre-Master Secret
2. 用伺服器公鑰(RSA)加密
3. 發送給伺服器
4. 伺服器用私鑰解密

問題:
駭客記錄所有加密流量(2020 年)
→ 未來取得伺服器私鑰(2025 年)
→ 解密 2020 年的流量
→ 看到所有通訊內容 ❌

前向保密(ECDHE):
1. 雙方各自產生「臨時」金鑰對
2. 交換公鑰
3. 計算共享密鑰
4. 用完就銷毀臨時私鑰

流程:
客戶端:
- 臨時私鑰:ecdhe_private_client
- 臨時公鑰:ecdhe_public_client

伺服器:
- 臨時私鑰:ecdhe_private_server
- 臨時公鑰:ecdhe_public_server

交換:
客戶端 → 伺服器:ecdhe_public_client
伺服器 → 客戶端:ecdhe_public_server

計算:
客戶端:ecdhe_private_client + ecdhe_public_server → 共享密鑰
伺服器:ecdhe_private_server + ecdhe_public_client → 共享密鑰
→ 相同的共享密鑰!

關鍵:
- 共享密鑰從未在網路上傳輸
- 臨時私鑰用完就銷毀
- 每次連線用不同的臨時金鑰

安全性:
駭客記錄所有流量(2020 年)
→ 未來取得伺服器長期私鑰(2025 年)
→ 仍然無法解密 2020 年的流量
→ 因為臨時私鑰已經銷毀了 ✅

TLS 支援:
TLS 1.2:可選(DHE/ECDHE 才支援)
TLS 1.3:強制(只支援 ECDHE)

檢查方法:
加密套件名稱包含 DHE 或 ECDHE
例:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

Q4:0-RTT 是什麼?有什麼風險?

A:立即恢復會話,但可能遭受重放攻擊

0-RTT(Zero Round Trip Time):

原理:
第一次連線:
ClientHello + KeyShare →
            ← ServerHello + ... + Session Ticket
Finished →
正常通訊

伺服器發送 Session Ticket(包含密鑰材料)

第二次連線(0-RTT):
ClientHello + Session Ticket + Early Data (HTTP Request) →
(不等握手完成,直接發送 HTTP 請求)

→ 完全沒有額外延遲!

優點:
✅ 最快(0 延遲)
✅ 用戶體驗最佳

風險:

1. 重放攻擊(Replay Attack)
駭客:攔截 0-RTT 請求
駭客:重新發送相同的請求
→ 如果是 POST /transfer(轉帳)
→ 可能重複執行 ❌

範例:
客戶端:0-RTT: POST /transfer?amount=1000
駭客:攔截並記錄
駭客:重新發送 100 次
→ 轉帳 100 次 ❌

2. 無前向保密
如果 Session Ticket 洩露
→ 可以解密 0-RTT 資料

防護措施:

1. 限制 0-RTT 用途
只允許冪等操作(GET)
禁止非冪等操作(POST, PUT, DELETE)

2. 伺服器防重放
- 記錄已使用的 Session Ticket
- 拒絕重複的 0-RTT 請求
- 限制 Session Ticket 有效期

3. 應用層檢查
- 加入 nonce(隨機數)
- 檢查請求時間戳
- 限制請求頻率

使用建議:
✅ 靜態資源(GET /style.css)
✅ 查詢操作(GET /search?q=keyword)
❌ 修改操作(POST /delete)
❌ 敏感操作(POST /login)

Nginx 設定:
ssl_early_data on;

應用層處理:
if request.headers.get('Early-Data') == '1':
    # 這是 0-RTT 請求
    if request.method != 'GET':
        # 拒絕非 GET 請求
        return 425  # Too Early

結論:
0-RTT 很快但有風險
只用於安全的冪等操作

Q5:握手失敗常見原因有哪些?

A:憑證問題、協定不相容、網路問題

常見原因:

1. 憑證過期
錯誤:ERR_CERT_DATE_INVALID
原因:憑證超過有效期
解決:更新憑證

2. 憑證域名不符
錯誤:ERR_CERT_COMMON_NAME_INVALID
原因:憑證是給 www.example.com,但訪問 example.com
解決:使用 SAN 包含兩個域名,或重新導向

3. 自簽憑證
錯誤:ERR_CERT_AUTHORITY_INVALID
原因:憑證不是由可信任 CA 簽發
解決:使用真正的 CA 憑證(Let's Encrypt)

4. 缺少中繼憑證
錯誤:ERR_CERT_AUTHORITY_INVALID
原因:伺服器沒有提供完整的憑證鏈
解決:設定 fullchain.crt(包含中繼憑證)

5. TLS 版本不相容
錯誤:ERR_SSL_VERSION_OR_CIPHER_MISMATCH
原因:
- 伺服器只支援 TLS 1.0(已棄用)
- 客戶端只支援 TLS 1.2+
解決:升級伺服器支援 TLS 1.2/1.3

6. 加密套件不相容
錯誤:ERR_SSL_VERSION_OR_CIPHER_MISMATCH
原因:客戶端和伺服器沒有共同支援的加密套件
解決:
# Nginx
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

7. SNI 問題
錯誤:SSL_ERROR_UNRECOGNIZED_NAME_ALERT
原因:伺服器不支援 SNI
解決:升級伺服器軟體

8. OCSP 問題
錯誤:ERR_CERT_REVOKED
原因:憑證已被撤銷
解決:重新申請憑證

9. 時間不同步
錯誤:ERR_CERT_DATE_INVALID
原因:客戶端時間不正確
解決:同步系統時間

10. 防火牆阻擋
錯誤:ERR_CONNECTION_TIMED_OUT
原因:防火牆阻擋 443 port
解決:開放 443 port

除錯工具:
1. SSL Labs(https://www.ssllabs.com/ssltest/)
   - 檢查伺服器 TLS 設定
   - 評分 A+ 最好

2. OpenSSL
   openssl s_client -connect example.com:443

3. curl -v
   curl -v https://example.com

4. Chrome DevTools
   - Network → 查看錯誤
   - Security → 查看憑證資訊

✅ 重點回顧

HTTPS 握手目的:

  • 驗證伺服器身份
  • 交換加密金鑰
  • 協商加密演算法

TLS 1.2 握手(2-RTT):

ClientHello →
            ← ServerHello + Certificate + ...
ClientKeyExchange + Finished →
            ← Finished

TLS 1.3 握手(1-RTT):

ClientHello + KeyShare →
            ← ServerHello + KeyShare + Certificate + Finished
Finished →

關鍵改進:

  • TLS 1.3 更快(1-RTT vs 2-RTT)
  • 0-RTT 支援(恢復會話)
  • 握手訊息加密(更好隱私)
  • 強制前向保密(ECDHE)

效能優化:

  • Session Resumption(會話恢復)
  • OCSP Stapling(減少延遲)
  • TLS False Start(提前發送資料)
  • 0-RTT(立即恢復會話)

憑證驗證:

  1. 檢查有效期
  2. 檢查域名
  3. 檢查憑證鏈
  4. 驗證簽章
  5. 檢查撤銷狀態

前向保密:

  • 使用臨時金鑰(ECDHE)
  • 每次連線不同金鑰
  • 即使私鑰洩露,過去通訊仍安全

0-RTT:

  • 優點:最快(0 延遲)
  • 風險:重放攻擊
  • 限制:只用於冪等操作(GET)

面試重點:

  • ✅ TLS 1.2 vs 1.3 握手差異
  • ✅ 憑證驗證流程
  • ✅ 前向保密的原理和重要性
  • ✅ 0-RTT 的優缺點
  • ✅ 握手失敗常見原因

上一篇: 03-3. 數位憑證與 CA 下一篇: 04-1. WebSocket 基礎概念


最後更新:2025-01-06

0%