在 无线与异构接入 中,看到了数据包如何通过 WiFi、5G 和卫星等无线介质接入互联网。至此,从 物理介质与编码 到无线接入,我们已经走过了数据包旅程的每一个环节。
现在是时候把所有知识串联起来了。本章将端到端追踪一个完整的 HTTP 请求——从浏览器输入 https://www.example.com 开始,到页面渲染完成,亲眼看到数据包穿越 WiFi、以太网交换、ARP 首跳、IP 路由、NAT 翻译、BGP 域间选路、MPLS 骨干网、CDN 边缘缓存的每一步。每一阶段都对应本系列的一个章节,每一层协议都将在抓包中现出原形。
一、实验场景设定
1.1 场景描述
用户在北京家中通过 WiFi 连接路由器,访问 https://www.example.com。数据包的完整路径:
1.2 网络参数
| 参数 | 值 |
|---|---|
| 用户 IP | 192.168.1.100(内网) |
| 路由器内网 IP | 192.168.1.1 |
| 路由器外网 IP | 110.242.68.1(中国电信) |
| DNS 服务器 | 119.29.29.29(DNSPod) |
| 目标域名 | www.example.com |
| CDN 边缘 IP | 203.0.113.50(北京 PoP) |
| 源站 IP | 198.51.100.10(上海数据中心) |
1.3 实验工具
# 抓包工具sudo apt install -y tshark tcpdump wireshark
# DNS 诊断sudo apt install -y dnsutils
# 路径追踪sudo apt install -y mtr-tiny traceroute
# HTTP 调试# curl 通常已预装
# TLS 调试# openssl 通常已预装
# 套接字统计# ss 通常已预装
# 开始抓包(在另一个终端)sudo tcpdump -i any -w full_trace.pcap \ "host 203.0.113.50 or host 119.29.29.29 or host 198.51.100.10"二、DNS解析阶段
2.1 触发DNS查询
浏览器输入 URL 后,第一步是解析域名。浏览器依次检查:浏览器缓存 → 操作系统缓存 → hosts 文件 → DNS 服务器。
# 用 dig 追踪完整解析路径dig +trace +verbose www.example.com @119.29.29.29
# 简单查询(只看结果)dig www.example.com A# ;; ANSWER SECTION:# www.example.com. 3600 IN A 203.0.113.50# ;; Query time: 15 msec
# 查询 CNAME 链(CDN 通常用 CNAME)dig www.example.com CNAME# www.example.com. 3600 IN CNAME www.example.com.cdn.example.net.# www.example.com.cdn.example.net. 300 IN A 203.0.113.502.2 Wireshark分析DNS报文
# 过滤 DNS 查询tshark -r full_trace.pcap -Y "dns.qr == 0" -T fields \ -e frame.time_relative -e ip.src -e ip.dst -e dns.qry.name# 0.000 192.168.1.100 119.29.29.29 www.example.com
# 过滤 DNS 响应tshark -r full_trace.pcap -Y "dns.qr == 1" -T fields \ -e frame.time_relative -e dns.a# 0.015 203.0.113.50
# DNS 报文结构tshark -r full_trace.pcap -Y "dns" -V -c 1# Domain Name System (query)# Transaction ID: 0x1234# Flags: 0x0100 Standard query# Questions: 1# Answer RRs: 0# Authority RRs: 0# Additional RRs: 0# Queries# www.example.com: type A, class INDNS 解析耗时约 15ms(本地递归服务器有缓存)。如果是冷启动,需要从根域名服务器开始迭代查询,耗时可能达到 100-300ms。这正是 DNS域名系统 中讨论的递归查询过程。
DNS 使用 UDP与传输基础 中介绍的 UDP 协议传输(端口 53),因为 DNS 查询通常很小(<512 字节),UDP 的低延迟优势明显。DNS 响应超过 512 字节时切换到 TCP(EDNS0 允许 UDP 承载更大报文)。
三、TCP连接建立
3.1 三次握手
DNS 解析拿到 IP 后,浏览器开始建立 TCP 连接。如果是 HTTPS,实际是先建立 TCP 再进行 TLS 握手。
# 用 tshark 观察三次握手tshark -r full_trace.pcap -Y "tcp.flags.syn == 1" -T fields \ -e frame.time_relative -e ip.src -e ip.dst -e tcp.srcport -e tcp.dstport -e tcp.flags# 0.016 192.168.1.100 203.0.113.50 54321 443 SYN# 0.022 203.0.113.50 192.168.1.100 443 54321 SYN,ACK# 0.023 192.168.1.100 203.0.113.50 54321 443 ACK
# 查看 SYN 包的选项tshark -r full_trace.pcap -Y "tcp.flags.syn == 1 && tcp.flags.ack == 0" -V -c 1# Options: (36 bytes)# MSS: 1460# SACK_PERM: True# Timestamps: TSval 12345678, TSecr 0# NOP# Window scale: 8 (multiply by 256)三次握手的时间线:
RTT 约 6ms——客户端到北京 CDN 边缘节点的延迟。这是 TCP连接管理 中讨论的三次握手过程,SYN 包携带了 MSS、窗口缩放、SACK 等选项。
3.2 用ss观察连接状态
# 查看已建立的 TCP 连接ss -tnp | grep 203.0.113.50# ESTAB 0 0 192.168.1.100:54321 203.0.113.50:443
# 查看连接的详细参数ss -ti dst 203.0.113.50# cubic wscale:8,7 rto:204 rtt:6.2/3.1 mss:1460 pmtu:1500# rcvmss:1260 advmss:1460 cwnd:10 ssthresh:32 bytes_acked:1# ↑ cwnd=10(慢启动初始窗口),ssthresh=32四、TLS握手
4.1 TLS 1.3握手
TCP 连接建立后,浏览器立即发起 TLS 握手。TLS 1.3 将握手简化为 1-RTT:
# 用 openssl 观察 TLS 握手openssl s_client -connect 203.0.113.50:443 -servername www.example.com -tlsextdebug </dev/null 2>&1 | head -30# TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384# Server Certificates:# subject: CN=www.example.com# issuer: C=US, O=DigiCert Inc, CN=DigiCert TLS RSA SHA256 2020 CA1# SSL-Session:# Protocol: TLSv1.3# Cipher: TLS_AES_256_GCM_SHA384
# 用 tshark 过滤 TLS 握手tshark -r full_trace.pcap -Y "tls.handshake.type > 0" -T fields \ -e frame.time_relative -e ip.src -e tls.handshake.type# 0.024 192.168.1.100 ClientHello (1)# 0.032 203.0.113.50 ServerHello (2)# 0.032 203.0.113.50 Certificate (11)# 0.032 203.0.113.50 CertificateVerify (15)# 0.032 203.0.113.50 Finished (20)# 0.033 192.168.1.100 Finished (20)TLS 1.3 握手只增加 1-RTT(约 8ms),加上 TCP 的 1-RTT,总连接建立开销约 14ms。如果启用 TLS 0-RTT(会话恢复),首次 HTTP 请求可以和 TLS Finished 一起发送,省掉一个 RTT。这正是 TLS与安全通道 中讨论的 TLS 1.3 优化。
五、HTTP请求与响应
5.1 发送HTTP/2请求
TLS 握手完成后,浏览器通过 ALPN 协商的 HTTP/2 协议发送请求:
# 用 curl 发送 HTTPS 请求并查看详细信息curl -v --http2 https://www.example.com/ 2>&1 | head -40# * ALPN, offering h2# * ALPN, server accepted h2# > GET / HTTP/2# > Host: www.example.com# > User-Agent: curl/8.x# > Accept: */*# ># < HTTP/2 200# < content-type: text/html; charset=UTF-8# < server: nginx# < x-cache: HIT# < age: 3600# < content-length: 1256# <# <!DOCTYPE html>...
# 注意 x-cache: HIT —— CDN 缓存命中,无需回源5.2 HTTP/2流多路复用
# 用 tshark 观察 HTTP/2 帧tshark -r full_trace.pcap -Y "http2" -T fields \ -e frame.time_relative -e http2.stream -e http2.type -e http2.length# 0.034 1 HEADERS 45 (请求头)# 0.035 1 DATA 0 (请求体为空)# 0.042 1 HEADERS 120 (响应头)# 0.042 1 DATA 1256 (响应体)# 0.043 3 HEADERS 35 (并发请求: /style.css)# 0.043 5 HEADERS 38 (并发请求: /app.js)
# Chrome DevTools Network 面板可以看到瀑布图# 在 Chrome 中按 F12 → Network → 查看 Timing 栏# Stalled → DNS Lookup → Initial connection → SSL → Request → Waiting → DownloadHTTP/2 的流多路复用让多个请求在同一个 TCP 连接上并行传输——stream 1 是 HTML,stream 3 是 CSS,stream 5 是 JS。没有 HTTP/1.1 的队头阻塞问题。这是 HTTP协议演进 中讨论的核心改进。
六、数据包的物理旅程
6.1 端到端路径追踪
# 用 mtr 追踪路径mtr --report --report-cycles 5 www.example.com# HOST: my-laptop Loss% Snt Last Avg Best Wrst# 1.|-- 192.168.1.1 0% 5 0.5 0.4 0.3 0.6 ← 家用路由器# 2.|-- 110.242.68.1 0% 5 3.2 3.5 2.8 4.1 ← 电信BRAS# 3.|-- 202.97.94.1 0% 5 5.1 5.3 4.8 6.2 ← 骨干网入口# 4.|-- 202.97.33.1 0% 5 6.3 6.5 5.9 7.8 ← 骨干网核心# 5.|-- 203.0.113.50 0% 5 6.8 7.0 6.2 8.1 ← CDN边缘
# 用 traceroute 看 MPLS 标签traceroute -M udp -n www.example.com# 1 192.168.1.1 0.5ms# 2 110.242.68.1 3.2ms MPLS Label=10019 CoS=0 TTL=253# 3 202.97.94.1 5.1ms MPLS Label=20018 CoS=0 TTL=252# 4 202.97.33.1 6.3ms# 5 203.0.113.50 6.8ms6.2 逐层解析数据包
拆解一个从客户端发出的 HTTP 请求包,看看每一层协议的贡献:
# 用 tshark 解码完整数据包tshark -r full_trace.pcap -V -c 1 -Y "tcp.stream == 0 && tcp.len > 0"| 层次 | 协议 | 字段 | 对应章节 |
|---|---|---|---|
| L1 | 物理层 | WiFi 6 802.11ax, MCS 9, 80MHz | 物理介质与编码 |
| L2 | 链路层 | 以太网帧, src=AA:BB:CC:DD:EE | 以太网与交换 |
| L2.5 | ARP | 192.168.1.1 → AA:BB:CC:DD:EE | ARP与首跳路由 |
| L3 | 网络层 | IP: src=192.168.1.100, dst=203.0.113.50, TTL=64 | IP地址与子网 |
| L3.5 | NAT | 192.168.1.100:54321 → 110.242.68.1:54321 | NAT与中间盒 |
| L3 | 路由 | IGP: 110.242.68.1 → 202.97.94.1 (OSPF) | 域内路由 |
| L3 | BGP | AS4134 → AS4808 (中国电信→CDN) | BGP与域间路由 |
| L2.5 | MPLS | Label=10019, 在骨干网中标签交换 | 运营商骨干网 |
| L4 | 传输层 | TCP: src=54321, dst=443, seq=101, ack=201 | TCP连接管理 |
| L4 | 拥塞控制 | cwnd=10 (慢启动), ssthresh=32 | TCP流控与拥塞控制 |
| L5 | 安全层 | TLS 1.3, AES_256_GCM, ECDHE | TLS与安全通道 |
| L7 | 应用层 | HTTP/2, GET /, stream=1 | HTTP协议演进 |
| - | CDN | x-cache: HIT, age: 3600 | CDN与内容分发 |
6.3 数据包大小分析
# 分析各层封装开销tshark -r full_trace.pcap -Y "tcp.stream == 0 && tcp.len > 0" -T fields \ -e frame.len -e ip.len -e tcp.len -e tls.record.length# 1514 1500 1460 1440# ↑ 以太网帧1514字节 = 14(以太网头) + 1500(IP包)# IP包1500字节 = 20(IP头) + 1480(TCP段)# TCP段1480字节 = 20(TCP头) + 1460(TCP有效载荷)# TLS记录1460字节 = 5(TLS头) + 1440(HTTP数据) + 16(AEAD标签)# 实际HTTP数据: 1440字节/帧| 封装层 | 头部大小 | 累计开销 |
|---|---|---|
| 以太网 | 14 字节 | 14 |
| IP | 20 字节 | 34 |
| TCP | 20 字节 | 54 |
| TLS 1.3 | 21 字节 (5头+16标签) | 75 |
| HTTP/2 | 9 字节 (帧头) | 84 |
| 有效载荷 | 1416 字节 | 84/1500 = 5.6% |
协议栈的总开销约 5.6%——这是互联网分层架构的代价,也是 互联网全景 中讨论的端到端原则的体现。
七、性能分析与优化
7.1 时序分析
# 用 curl 的 -w 选项测量各阶段耗时curl -o /dev/null -s -w "\DNS: %{time_namelookup}s\n\TCP: %{time_connect}s\n\TLS: %{time_appconnect}s\n\TTFB: %{time_starttransfer}s\n\Total: %{time_total}s\n\Download: %{size_download} bytes\n" \https://www.example.com/
# 典型结果(CDN命中):# DNS: 0.003s (本地缓存)# TCP: 0.009s (1-RTT)# TLS: 0.017s (1-RTT)# TTFB: 0.025s (请求+响应)# Total: 0.032s (含下载)# Download: 1256 bytes7.2 优化前后对比
| 优化措施 | 优化前 | 优化后 | 节省 | 对应章节 |
|---|---|---|---|---|
| DNS 预解析 | 100ms(冷查询) | 3ms(缓存) | 97ms | DNS域名系统 |
| DNS 预连接 | - | 省去后续DNS查询 | 持续收益 | DNS域名系统 |
| TCP Fast Open | 6ms(1-RTT) | 0ms(0-RTT) | 6ms | TCP连接管理 |
| TLS 会话恢复 | 8ms(1-RTT) | 0ms(0-RTT PSK) | 8ms | TLS与安全通道 |
| HTTP/2 多路复用 | 3×RTT(串行) | 1×RTT(并行) | 12ms | HTTP协议演进 |
| CDN 边缘缓存 | 30ms(回源) | 7ms(命中) | 23ms | CDN与内容分发 |
| BBR 拥塞控制 | 慢启动慢 | 带宽探测快 | ~10ms | TCP流控与拥塞控制 |
| QUIC 0-RTT | 14ms(TCP+TLS) | 6ms(QUIC) | 8ms | QUIC与HTTP/3 |
| 总计 | ~200ms | ~32ms | ~168ms | — |
现代浏览器的性能优化远不止这些:预连接(preconnect)、预加载(preload)、HTTP/3 0-RTT、Service Worker 缓存、Brotli 压缩等。但所有这些优化的基础是对协议栈的深入理解——这正是本系列的目标。
7.3 用Wireshark IO图分析吞吐量
# 生成 IO 图数据tshark -r full_trace.pcap -q -z io,stat,1# Interval | Frames | Bytes# 0-1s | 45 | 52340# 1-2s | 12 | 8760
# 在 Wireshark 中查看 IO 图# Statistics → I/O Graph# 可以看到 TCP 吞吐量随时间的变化# 慢启动阶段吞吐量指数增长,拥塞避免阶段线性增长八、全系列回顾
8.1 章节与数据包旅程映射
| 阶段 | 数据包发生了什么 | 章节 |
|---|---|---|
| 物理层 | WiFi 6 将比特编码为 OFDM 符号,通过 5GHz 无线电波传输 | 物理介质与编码 |
| 链路层 | 802.11 帧经 CSMA/CA 竞争空口,AP 转发为以太网帧 | 以太网与交换 |
| 首跳 | ARP 解析默认网关 MAC,数据包找到第一跳路由器 | ARP与首跳路由 |
| 寻址 | IP 包 src=192.168.1.100, dst=203.0.113.50 | IP地址与子网 |
| NAT | 家用路由器将 192.168.1.100:54321 翻译为 110.242.68.1:54321 | NAT与中间盒 |
| 域内 | OSPF 计算到骨干网入口的最短路径 | 域内路由 |
| 域间 | BGP 选择 AS4134→AS4808 的跨域路径 | BGP与域间路由 |
| 安全 | RPKI 验证 203.0.113.0/24 属于 AS4808 | BGP安全与路由信任 |
| 骨干 | MPLS 标签交换穿越电信骨干网 | 运营商骨干网 |
| 交换 | IXP 路由服务器将流量导向 CDN | IXP与互联网交换 |
| 传输 | UDP 承载 DNS 查询,TCP 承载 HTTP 数据 | UDP与传输基础 |
| 连接 | TCP 三次握手建立连接,四次挥手释放 | TCP连接管理 |
| 流控 | 慢启动 cwnd 从 10 增长到 ssthresh | TCP流控与拥塞控制 |
| 未来 | QUIC 0-RTT + 无队头阻塞 | QUIC与HTTP/3 |
| 命名 | DNS 递归查询将域名解析为 IP | DNS域名系统 |
| 加密 | TLS 1.3 ECDHE 密钥交换 + AES-GCM 加密 | TLS与安全通道 |
| 应用 | HTTP/2 流多路复用 + HPACK 头部压缩 | HTTP协议演进 |
| 分发 | CDN 边缘缓存命中,x-cache: HIT | CDN与内容分发 |
| 终点 | 数据中心 CLOS 架构 + 负载均衡 | 数据中心与SDN网络 |
| 接入 | WiFi 6 OFDMA + CSMA/CA 接入 | 无线与异构接入 |
8.2 核心设计原则回顾
贯穿全系列的几个核心设计原则:
- 端到端原则:智能在边缘,网络核心尽量简单。TCP 的可靠性由端点保证,路由器只做转发
- 分层解耦:每一层只关心本层的协议,IP 不关心物理介质,TCP 不关心路由路径
- 策略优于最优:BGP 按策略选路而非最短路径,这是互联网的商业现实
- 信任但验证:RPKI 验证路由通告,TLS 验证服务器身份,DNSSEC 验证域名数据
- 缓存无处不在:DNS 缓存、CDN 缓存、浏览器缓存——每一层都在用空间换时间
- 冗余与故障隔离:BGP 多路径、Anycast 多节点、数据中心多链路——单点故障不可接受
- 演进而非替换:HTTP/2 没有替换 HTTP/1.1 的语义,QUIC 没有替换 TCP 的可靠性——新协议是旧协议的演进,不是革命
8.3 从”会上网”到”理解互联网”
22 章之前,你可能只知道 ping 通了就行、curl 返回 200 就行。现在你知道了:
ping不通但服务正常?可能是 NAT 丢弃了 ICMPtraceroute显示路径绕远?可能是 BGP 策略路由的结果- HTTPS 证书错误?可能是 TLS 证书链验证失败
- 网页打开慢?可能是 TCP 慢启动 还没跑满带宽
- CDN 为什么能加速?任播路由 + 边缘缓存
- BGP 劫持是怎么回事?路由信任缺陷 + RPKI 修复
互联网不是一个黑盒——它是一套精心设计的协议体系,每个协议都在解决一个特定问题。理解了这些协议的设计动机和工程现实,你就从”会上网”进阶到了”理解互联网”。
感谢你完成了这趟互联网运作的深入之旅。从物理介质中比特的编码,到应用层 HTTP 请求的抵达,追踪了数据包的每一步。互联网的伟大之处不在于它的复杂,而在于这些复杂度被分层封装得如此优雅——每一层都只做自己的事,每一层都对上层透明。这正是互联网能够从 ARPANET 成长为今天连接 50 亿人的全球网络的根本原因。
如果你还想继续深入,以下方向值得探索:
- 高性能网络:DPDK/XDP/RDMA 如何绕过内核协议栈,实现百万级 PPS 转发
- eBPF 网络编程:用 BPF 程序实现可编程的数据包处理,从 XDP 到 TC
- 容器网络:CNI 如何为容器组网,从 bridge 到 VXLAN 到 eBPF
- 服务网格:Istio/Linkerd 如何用 sidecar 代理实现流量治理
互联网的协议栈是一座永远在演进的大厦——HTTP/3 刚落地,HTTP/4 已在讨论;TLS 1.3 刚普及,后量子密码学已在路上;IPv6 部署了 20 年才过半,SRv6 又带来了新的可能。理解了协议的设计动机和工程现实,你就能跟上每一次演进,甚至参与其中。
本系列所有实验均可在 Linux 环境下复现。推荐使用 Ubuntu 22.04 LTS + Wireshark + GNS3 + FRR 的组合。如果你在实验中遇到问题,欢迎在系列讨论区交流。
参考
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时






