一次 HTTPS 请求从应用层到物理层的完整旅程,逐层追踪数据封装/解封装过程。 synthesis 页:跨 HTTP协议/TLS协议/TCP协议/DNS协议/ARP协议/ICMP协议 综合分析。
1. 全景拓扑:协议栈封装与解封装
先看一张协议栈全景图,自上而下是发送方的封装过程,自下而上是接收方的解封装过程,本文所有阶段都能在上面找到位置:
scss
发送方(封装) 接收方(解封装)
────────── ──────────
┌─────────────────────────────────────┐
│ 应用层 HTTP 请求行+头部+体 │ ← 生成数据
└────────────────┬────────────────────┘
│ +TLS Record 头(5B) +AEAD 标签(16B)
┌────────────────┴────────────────────┐
│ 安全层 TLS Record(AES-GCM 加密) │ ← 加密
└────────────────┬────────────────────┘
│ +TCP 头(20B)
┌────────────────┴────────────────────┐
│ 传输层 TCP 段(seq/ack/窗口/端口) │ ← 分段
└────────────────┬────────────────────┘
│ +IP 头(20B)
┌────────────────┴────────────────────┐
│ 网络层 IP 包(src/dst/TTL/协议) │ ← 路由
└────────────────┬────────────────────┘
│ +以太网帧头(14B) +FCS(4B)
┌────────────────┴────────────────────┐
│ 链路层 以太网帧(src MAC/dst MAC) │ ← ARP 查询
└────────────────┬────────────────────┘
│ 编码(8B/10B 或 PAM-4)
┌────────────────┴────────────────────┐
│ 物理层 电信号/光信号/无线电磁波 │ ← 物理传输
└─────────────────────────────────────┘
│
↓ ← 逐跳转发(路由器只处理到网络层)
│
┌─────────────────────────────────────┐
│ 物理层 → 链路层 → 网络层 → 传输层 │ ← 逐层解封装
│ → TLS 解密 → HTTP 解析 → 应用代码 │ ← 校验+路由
└─────────────────────────────────────┘
对照速记:应用层管"说什么",安全层管"加密说",传输层管"分段说",网络层管"送到哪",链路层管"下一跳",物理层管"怎么传"。
2. 场景:浏览器访问 www.example.com/page
2.0. 阶段 0:DNS 解析
ini
浏览器 → 本地 DNS 解析器 → 根 → TLD → 权威 → 返回 IP
协议栈:
应用层:DNS Query (www.example.com, type=A)
传输层:UDP 头 (src=随机, dst=53)
网络层:IP 头 (src=本机IP, dst=DNS服务器IP)
链路层:以太网帧 (src=本机MAC, dst=网关MAC)
scss
DNS 解析流程拓扑:
浏览器
│
├── 本地缓存命中? ──是──▶ 返回 IP(0ms)
│
├── 系统缓存命中? ──是──▶ 返回 IP(<1ms)
│
└── 向 DNS 服务器查询
│
├── 递归查询:本地 → 根 → TLD(.com) → 权威(example.com)
│
└── 返回 IP(5~50ms)
专家视角 :DNS 查询在 HTTPS 请求之前发生------浏览器先解析域名拿到 IP,才能建 TCP 连接。DNS 走 UDP协议 是为了省握手开销,但 DoH/DoT 走 TCP协议/HTTPS协议 加密。
2.1. 阶段 1:TCP 三次握手
ini
协议栈:
传输层:TCP 头 (SYN, seq=ISN, src=随机端口, dst=443)
网络层:IP 头 (src=本机IP, dst=服务器IP, TTL=64)
链路层:以太网帧 (src=本机MAC, dst=网关MAC)
↓ ARP 查询网关 MAC(若缓存未命中)
物理层:电信号/光信号
ini
TCP 三次握手时序:
客户端 服务器
│ │
│ ── SYN (seq=ISN_c) ──────────────▶│ 第1次:我要连接
│ │
│ ◀── SYN+ACK (seq=ISN_s, ack=ISN_c+1) ──│ 第2次:同意,我也要连接
│ │
│ ── ACK (ack=ISN_s+1) ────────────▶│ 第3次:确认你的连接
│ │
│ ═══ 连接建立,可发数据 ════════════│
2.2. 阶段 2:TLS 握手
scss
协议栈(TLS 1.3,1-RTT):
应用层:TLS ClientHello (密码套件列表, key_share, SNI)
传输层:TCP 头 (PSH+ACK, seq, ack)
网络层:IP 头
链路层:以太网帧
scss
TLS 1.3 握手时序(1-RTT):
客户端 服务器
│ │
│ ── ClientHello ──────────────────▶│ 密码套件 + key_share + SNI
│ (含 ECDHE 公钥) │
│ │
│ ◀── ServerHello + 证书 + Finished │ 选定套件 + key_share + 签名
│ (含 ECDHE 公钥 + AEAD 密钥) │
│ │
│ ── Finished ─────────────────────▶│ 验证完成
│ │
│ ═══ 会话密钥协商完成,可发加密数据 │
2.3. 阶段 3:HTTP 请求
swift
协议栈:
应用层:HTTP 请求行 + 头部 + 体
"GET /page HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"Accept: text/html\r\n"
"Cookie: session=abc123\r\n"
"\r\n"
↓ TLS 加密(AES-GCM,会话密钥)
安全层:TLS Record (加密的 HTTP 数据)
↓ TCP 分段(若 HTTP 请求 > MSS)
传输层:TCP 段 (PSH+ACK, seq, ack, 窗口)
↓ IP 路由(查路由表,选出接口)
网络层:IP 包 (src, dst, TTL, 协议=TCP)
↓ ARP 查询下一跳 MAC
链路层:以太网帧 (src=出接口MAC, dst=下一跳MAC)
↓ 物理层编码(8B/10B 或 PAM-4)
物理层:电信号/光信号/无线电磁波
swift
HTTP 请求逐层封装拓扑:
┌───────────────────────────────────────────────┐
│ 应用层 "GET /page HTTP/1.1\r\nHost: ...\r\n" │ 500B HTTP 体 + 300B 头
└───────────────────────┬───────────────────────┘
│ TLS 加密(AES-GCM)
┌───────────────────────┴───────────────────────┐
│ 安全层 TLS Record(5B头 + 密文 + 16B标签) │ +21B 开销
└───────────────────────┬───────────────────────┘
│ TCP 分段
┌───────────────────────┴───────────────────────┐
│ 传输层 TCP 段(20B头 + 数据) │ +20B 开销
└───────────────────────┬───────────────────────┘
│ IP 封装
┌───────────────────────┴───────────────────────┐
│ 网络层 IP 包(20B头 + TCP 段) │ +20B 开销
└───────────────────────┬───────────────────────┘
│ 以太网封装
┌───────────────────────┴───────────────────────┐
│ 链路层 以太网帧(14B头 + IP包 + 4B FCS) │ +18B 开销
└───────────────────────┬───────────────────────┘
│ 物理编码
┌───────────────────────┴───────────────────────┐
│ 物理层 电信号/光信号 │ 879B 总计
└───────────────────────────────────────────────┘
2.4. 阶段 4:逐跳转发
markdown
路由器收到 IP 包:
1. 链路层:解封装,取出 IP 包
2. 网络层:TTL--, 查路由表最长前缀匹配
3. 若 TTL=0 → 丢包 + ICMP Time Exceeded
4. 否则:查 ARP 获取下一跳 MAC → 重新封装 → 转发
5. TCP/TLS/HTTP 层内容不变(只改 IP 和链路层头)
ini
逐跳转发拓扑(IP 端到端不变,MAC 每跳重写,TTL 每跳递减):
客户端 路由器 R1 路由器 R2 服务器
10.1.1.2 10.1.1.1/10.3.3.1 10.3.3.2/10.2.2.1 10.2.2.2
│ │ │ │
│ 帧[MAC-A→MAC-B] │ │ │
├─────────────────▶│ TTL:64→63 │ │
│ │ 帧[MAC-C→MAC-D] │ │
│ ├──────────────────▶│ TTL:63→62 │
│ │ │ 帧[MAC-E→MAC-F] │
│ │ ├──────────────────▶│
│ │ │ │
└──────────────────┴───────────────────┴───────────────────┘
IP 头(全程不变):源 10.1.1.2 ──────────────────────▶ 目的 10.2.2.2
MAC 帧(每跳重写):每段链路只填"本段的下一跳" MAC
TTL:64 →(R1) 63 →(R2) 62 (减到 0 = 丢弃 + 回 ICMP Time Exceeded)
专家视角 :中间路由器只处理到网络层------它不看 TCP/TLS/HTTP 内容(除非做 DPI)。这是分层架构的效率优势:路由器不需要理解 HTTP 就能转发 HTTP 流量。NAT 是例外------它改 TCP 端口和 IP 地址,触碰了传输层。
2.5. 阶段 5:服务器接收与响应
perl
服务器协议栈(自下而上解封装):
物理层 → 链路层(校验 FCS)→ 网络层(校验 IP 校验和)
→ 传输层(校验 TCP 校验和,查 socket 四元组)
→ TLS 解密 → HTTP 解析 → 路由到应用代码
→ 生成 HTTP 响应 → TLS 加密 → TCP → IP → 链路层 → 发出
markdown
服务器解封装与响应拓扑:
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│物理层│───▶│链路层│───▶│网络层│───▶│传输层│───▶│TLS │───▶│HTTP │
│ │ │校验FCS│ │校验IP│ │校验TCP│ │解密 │ │解析 │
│ │ │ │ │路由表│ │socket│ │ │ │路由 │
└──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──┬───┘
│
应用代码处理
│
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ └──┬───┘
│物理层│◀───│链路层│◀───│网络层│◀───│传输层│◀───│TLS │◀───│HTTP │
│ │ │封装帧│ │封装IP│ │封装TCP│ │加密 │ │响应 │
└──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘
3. 数据包大小估算
markdown
HTTP 请求体(假设 500 字节)
+ HTTP 头部(~300 字节) = 800 字节
+ TLS Record 头(5 字节)+ AEAD 标签(16 字节) = 821 字节
+ TCP 头部(20 字节,无选项) = 841 字节
+ IP 头部(20 字节) = 861 字节
+ 以太网帧头(14 字节)+ FCS(4 字节)= 879 字节
scss
数据包大小逐层累加拓扑:
应用层 ████████████████████████████████ 800B (HTTP 头+体)
安全层 █████████████████████████████████ 821B (+21B TLS)
传输层 ██████████████████████████████████ 841B (+20B TCP)
网络层 ███████████████████████████████████ 861B (+20B IP)
链路层 ████████████████████████████████████ 879B (+18B Ethernet)
协议开销 = 879 - 500 = 379B(75% 开销率)
专家视角 :一个 500 字节的 HTTP 请求,到链路层变成 879 字节------协议开销 75%。这是为什么 HTTP/2 头部压缩(HPACK)和 HTTP/3 多路复用如此重要:减少头部开销和连接数。
4. MTU 与分片
ini
以太网 MTU = 1500 字节
- IP 头 20 - TCP 头 20 = MSS 1460 字节
- TLS Record 头 5 + 标签 16 = 有效载荷 1439 字节
若应用数据 > 1439 字节 → TLS 分多个 Record
若 TCP 段 > 1460 字节 → 不会分片(MSS 协商保证)
若 IP 包 > 1500 字节 → IP 分片(应避免)
yaml
MTU 分层约束拓扑:
┌─────────────────────────────────────────────────────┐
│ 以太网 MTU = 1500 字节 │
│ ┌───────────────────────────────────────────────┐ │
│ │ IP 包 ≤ 1500 │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ TCP 段 ≤ 1460(MSS = MTU - IP头 - TCP头)│ │ │
│ │ │ ┌───────────────────────────────────┐ │ │ │
│ │ │ │ TLS Record ≤ 1439(MSS - TLS开销) │ │ │ │
│ │ │ │ ┌─────────────────────────────┐ │ │ │ │
│ │ │ │ │ HTTP 有效载荷 ≤ 1439 │ │ │ │ │
│ │ │ │ └─────────────────────────────┘ │ │ │ │
│ │ │ └───────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
PPPoE MTU = 1492(-8B PPPoE头)→ MSS 1452 → 需 PMTUD 探测
专家视角 :TCP MSS 钳制 是避免 IP 分片的关键------握手时双方协商 MSS ≤ MTU-40。但跨网络 MTU 可能更小(如 PPPoE 1492),需 PMTUD 探测。PMTUD 黑洞(ICMP 3/4 被防火墙丢弃)是常见性能问题。
5. 完整时序
时间 事件 协议层
0ms DNS 查询 DNS/UDP/IP
5ms DNS 响应 DNS/UDP/IP
10ms TCP SYN TCP/IP
15ms TCP SYN-ACK TCP/IP
16ms TCP ACK + TLS ClientHello TCP/TLS/IP
21ms TLS ServerHello + 证书 TCP/TLS/IP
22ms TLS Finished TCP/TLS/IP
23ms HTTP 请求 HTTP/TLS/TCP/IP
28ms HTTP 响应 HTTP/TLS/TCP/IP
30ms 页面渲染开始
vbscript
完整 HTTPS 请求时序拓扑:
时间 客户端 服务器
0ms ── DNS Query ──────────────────────▶ DNS 服务器
5ms ◀── DNS Response ──────────────────
10ms ── TCP SYN ────────────────────────▶
15ms ◀── TCP SYN+ACK ───────────────────
16ms ── TCP ACK + TLS ClientHello ──────▶
21ms ◀── TLS ServerHello + 证书 ─────────
22ms ── TLS Finished ───────────────────▶
23ms ── HTTP 请求 ──────────────────────▶
28ms ◀── HTTP 响应 ─────────────────────
30ms 页面渲染开始
首次 HTTPS ≈ 30ms(同机房)
DNS 5ms + TCP 10ms + TLS 10ms + HTTP 5ms
专家视角 :首次 HTTPS 请求约 30ms(同机房),其中 DNS 5ms + TCP 握手 10ms + TLS 握手 10ms + HTTP 往返 5ms。TLS 1.3 0-RTT 可省到 20ms,HTTP/3 连接迁移可省重连开销。