Appearance
第1章 一次网络请求是怎样发生的
在浏览器地址栏输入 https://example.com/learn?id=7 并按下回车后,页面通常会瞬间呈现在我们眼前。在这短短几百毫秒内,计算机其实在后台飞速完成了一系列复杂操作:名称解析、路径选择、局域网交付、TCP 建连、TLS 协商以及最终的 HTTP 交互。理清这条链路,能帮我们建立全局视角,后续再看 TCP 的各个字段时就能知道它们所处的位置和作用了。
TLS 是什么?
TLS(Transport Layer Security,传输层安全协议)在可靠传输之上提供身份认证、机密性和数据完整性保护。HTTPS 通常把 HTTP 消息放入 TLS 记录,再通过 TCP 或 QUIC 传输。
TLS 保护连接中的内容,同时不会替代应用层鉴权、业务授权和容量控制。
先做一个预测
如果让你凭直觉给下面这些事件排序,你会怎么排?
- 查询域名对应的 IP 地址
- 选择出口网卡(网络接口)和下一跳
- 必要时解析下一跳的链路层地址(MAC 地址)
- 建立 TCP 连接
- 发送 HTTP 请求
- 协商 TLS 加密参数
- 读取 HTTP 响应
对于访问目标站点的一条全新 HTTPS 连接,常规的执行顺序是:DNS 解析 → 路由选择 → 必要时执行 ARP 或 IPv6 ND → TCP 建连 → TLS 握手 → HTTP 交互。 当然,如果 DNS 解析需要通过网络查询,这个查询动作本身也会走一遍路由选择和链路交付的流程。为了更加聚焦,我们这里的顺序主要是指拿到目标站点的 IP 后的建连过程。在实际场景中,DNS 缓存、*连接复用(Keep-Alive)*或者代理服务器的存在,都可能让其中的某些步骤直接跳过,复用现成的结果。
HTTPS 是什么?
HTTPS 可以理解为“通过 TLS 保护的 HTTP”。客户端先与服务器建立传输连接并完成 TLS 握手,再在加密通道里交换 HTTP 消息;常见默认端口是 TCP 443。
加密覆盖 HTTP 的请求路径、首部和正文,外层 IP 地址、TCP 端口、包长和时间等传输元数据通常仍可从普通抓包中观察。
DNS 解析是什么?
DNS(Domain Name System,域名系统)是一套分层、分布式的命名系统。DNS 解析会把应用使用的主机名查询成一个或多个地址记录,供客户端选择目标 IP;它还能承载邮件路由、服务发现等其他记录类型。
“解析成功”只代表拿到了记录,后续仍需通过路由、TCP 和应用协议验证目标是否真正可达。
路由选择是什么?
路由选择是操作系统依据目标 IP 查询本机路由表,决定从哪个网络接口发送、采用哪个源 IP,并把包交给哪个下一跳的过程。路径上的每台路由器也会进行类似判断。
DNS 决定“可能连接哪个地址”,路由选择决定“数据怎样朝这个地址迈出下一跳”。
ARP 是什么?
ARP(Address Resolution Protocol,地址解析协议)用于 IPv4 局域网:主机已知下一跳 IPv4 地址时,通过广播询问并缓存对应的链路层 MAC 地址,随后才能封装 Ethernet 帧。
ARP 只解决当前链路上的交付问题,不会查询远端公网服务器一路沿途的 MAC 地址。
IPv6 ND 是什么?
IPv6 ND(Neighbor Discovery,邻居发现)是一组基于 ICMPv6 的机制,承担邻居地址解析、路由器发现、前缀发现和邻居可达性检测等任务。NDP 是 Neighbor Discovery Protocol 的常见简称。
它在 IPv6 中覆盖了 IPv4 网络里 ARP 的主要职责,并提供了更多链路配置能力。
TLS 握手是什么?
TLS 握手是客户端与服务器在传输应用数据前协商协议版本和加密参数、认证服务器身份并导出会话密钥的过程。握手成功后,双方使用这些密钥保护后续 TLS 记录。
它会增加一次或多次网络往返;会话恢复等机制可以缩短后续连接的握手成本。
DNS 缓存是什么?
DNS 缓存会把查询结果连同有效期暂存于浏览器、操作系统、递归解析器等位置。有效期内再次查询可以直接复用结果,减少延迟和 DNS 流量。
缓存项通常受记录 TTL 约束;抓包里没有 DNS 报文时,缓存命中是常见原因之一。
Keep-Alive 连接复用是什么?
这里的 Keep-Alive 指 HTTP 持久连接:一个请求完成后暂时保留底层连接,让后续请求继续复用,从而省去重复的 TCP 和 TLS 握手。
它与操作系统的 TCP Keepalive 探测机制名称相近、用途不同;后者用于发现长期空闲连接是否仍然存活。
第一步:解析 URL
URL 是应用层用来描述资源位置的。我们以 https://example.com/learn?id=7 为例:
URL 是什么?
URL(Uniform Resource Locator,统一资源定位符)是资源定位标识。它通常由协议方案、主机名、可选端口、路径、查询参数和片段组成,例如 https://example.com:443/learn?id=7。
网络连接主要使用其中的主机名、协议方案和端口;路径与查询参数会在连接建立后作为应用层请求的一部分发送。
| 组成部分 | 值 | 作用 |
|---|---|---|
| 协议方案 (Scheme) | https | 指定使用 HTTPS 协议,默认目标端口为 443 |
| 主机名 (Hostname) | example.com | 交给 DNS 系统去解析成 IP 地址 |
| 路径 (Path) | /learn | 告诉服务器我们要访问哪个具体资源 |
| 查询参数 (Query) | id=7 | 传递给应用层的业务参数 |
*主机名(Hostname)和域名(Domain Name)*主要是为了方便人类记忆和应用程序使用。但是在网络底层,发送 IP 数据报必须要有目标 IP 地址,所以客户端紧接着要做的就是把域名解析成 IP。另外,如果你在 URL 里显式指定了端口(比如 https://example.com:8443),它就会覆盖掉协议自带的默认端口。
主机名是什么?
主机名是应用用来指代某台主机或某个服务端点的名称。URL 中 example.com 所在的位置是主机名;它既可以是完整域名,也可以是本地网络能解析的短名称。
一个主机名可以解析到多个 IP,同一个 IP 也可以承载多个主机名,因此主机名与机器之间并非固定的一对一关系。
域名是什么?
域名是 DNS 命名树中的名称,例如 example.com。从右向左可看到顶级域 com 及其下的 example;完整域名还能继续包含 www 等子域标签。
日常语境常把 URL 中的主机名直接称为域名。严谨分析时,可以结合它在 URL、DNS 记录和 TLS 证书中的具体角色判断含义。
第二步:通过 DNS 获取候选 IP
拿到主机名后,DNS 解析器就会去查找对应的地址记录。如果是 IPv4,通常找的是 A 记录;如果是 IPv6,则是 AAAA 记录。DNS 查询往往会返回多个候选 IP,应用程序会根据系统策略、网络可达性以及建连速度等因素,挑一个来用。
DNS 解析器是什么?
DNS 解析器是代替应用完成 DNS 查询的组件。应用通常调用操作系统提供的存根解析器;存根解析器再向配置好的递归 DNS 服务器发问,并把结果交还给应用。
浏览器也可能内置缓存、加密 DNS 客户端和地址选择逻辑,因此最终查询路径需要结合实际软件与配置判断。
A 记录保存什么?
DNS 的 A(Address)记录把一个名称映射到一个 IPv4 地址。例如,某次查询可能得到 example.com. A 93.184.216.34;记录本身不保存端口,也不保证该地址上的服务一定可达。
一个名称可以拥有多条 A 记录,客户端或负载均衡策略会从候选地址中选择。
IPv6 是什么?
IPv6 是互联网协议的第 6 版,地址长度为 128 位,通常使用十六进制和冒号表示,例如 2001:db8::10。它提供巨大的地址空间,并以邻居发现、扩展首部等机制调整了 IPv4 的部分设计。
IPv4 与 IPv6 可以在同一设备和应用中并存;一次访问最终走哪一版,需要结合 DNS 结果、路由和连接策略判断。
AAAA 记录保存什么?
DNS 的 AAAA(读作 “quad-A”)记录把一个名称映射到一个 IPv6 地址。名称中的四个 A 源于 IPv6 地址长度是 IPv4 的四倍;它与 TLS、HTTP 版本没有直接关系。
只有在本机具备可用 IPv6 路由时,拿到 AAAA 记录后发起的 IPv6 连接才可能成功。
真实的 DNS 查询过程可能会经过层层关卡:浏览器缓存、操作系统缓存、本地路由器配置的递归 DNS,最后才是上游的权威 DNS 服务器。只要在前面的任何一层命中了缓存,我们在抓包时就看不到 DNS 流量,直接进入下一步了。这也是抓包分析时的一个常识:抓包只能记录在你抓包期间、流经你这台机器网卡的实际报文。
DNS 记录还会携带 TTL(Time to Live),告诉缓存这份结果最多还能复用多长时间。
DNS 记录的 TTL 是什么?
DNS TTL 是权威记录给缓存的有效期,单位为秒。递归解析器或操作系统缓存通常会让剩余 TTL 随时间递减,归零后重新查询;它控制缓存时长,不保证所有更新会在同一瞬间全球可见。
DNS TTL 与 IP 首部中的 TTL 名称相同、语义独立:前者约束缓存寿命,后者限制数据报可经过的转发跳数。
递归 DNS 是什么?
递归 DNS 服务器接受客户端的完整查询请求,并负责从缓存或 DNS 层级中寻找最终答案。需要外出查询时,它会依次访问根、顶级域和相关权威服务器,再把结果缓存后返回。
家庭路由器常把查询转发给运营商或公共递归解析服务,所以本机看到的 DNS 对端未必是最终保存记录的服务器。
权威 DNS 服务器是什么?
权威 DNS 服务器保存并发布某个 DNS 区域的正式记录,对该区域给出权威答案。它回答“该区域配置了什么”,通常不替普通客户端递归查询其他域名。
修改域名记录后,各层旧缓存会按 TTL 逐渐过期,因此不同查询者在传播期间可能得到不同结果。
DNS 的核心职责就是回答“这个域名对应哪些 IP”。有了 IP,再加上前面从 URL 或者协议默认配置中得到的端口,我们就拼出了 TCP 尝试连接的完整远端地址(比如 <目标 IP>:443)。由于 CDN 和负载均衡的存在,不同时间、不同网络环境下解析出来的 IP 可能会不一样,所以做实验时,要以你电脑当时的实际输出为准。
CDN 是什么?
CDN(Content Delivery Network,内容分发网络)把内容或代理节点部署到多个地区,让用户连接较近或较合适的边缘节点。DNS 调度、Anycast 和应用层重定向都可以参与节点选择。
因此,同一域名在不同地点、运营商或时间解析到不同 IP 很常见,排障记录应保留当时的 DNS 结果和实际连接地址。
负载均衡是什么?
负载均衡把多个请求或连接分配给一组后端实例,以提升容量、可用性和维护灵活度。它可以发生在 DNS、IP/TCP 四层或 HTTP 七层,每种方式对抓包所见的地址、连接和应用消息影响不同。
“解析到哪个 IP”与“最终由哪个后端处理”可能是两个独立选择。
第三步:选择路由与下一跳
操作系统拿到目标 IP 后,会在本机的路由表中进行“最长前缀匹配”(Longest Prefix Match),以此来决定以下三件事:
路由表是什么?
路由表是一组“目标网络前缀 → 出口接口、下一跳和度量”等规则。最长前缀匹配会优先选择覆盖目标地址且前缀最具体的规则;没有更具体规则时,通常落到默认路由。
路由表描述的是本机下一步怎样发送,完整的端到端路径还取决于沿途设备各自的路由决定。
- 数据包该从哪个*网卡(网络接口)*发出去。
- 应该使用哪个本地源 IP。
- 数据包的*下一跳(Next Hop)*是直接发给目标主机,还是得先发给路由器。
网卡和网络接口是什么?
网络接口是操作系统发送和接收网络数据的逻辑入口,可以对应物理网卡、Wi-Fi 适配器、回环接口、隧道或虚拟网卡。网卡通常偏向指物理或虚拟适配器硬件,系统工具里“接口”范围更广。
一台机器可以同时拥有多个接口和多个 IP,路由选择会决定某个目标实际走哪一个。
下一跳是什么?
下一跳是当前设备准备把数据报交给的下一个 IP 节点。目标在同一链路时,下一跳就是目标主机;跨网段时,下一跳通常是路由器或默认网关。
链路层帧的目标 MAC 指向下一跳,IP 数据报的目标 IP 仍指向最终目的地。
如果目标 IP 就在同一个局域网内,机器就可以直接把它作为下一跳。但如果要跨网段访问(比如访问外网),数据包通常会被扔给默认网关(Default Gateway)。路由器收到这个 IP 数据报后,也会查自己的路由表,就这样接力般地一跳一跳把数据送到目的地。
默认网关是什么?
默认网关是本机在没有更具体路由时使用的下一跳路由器。IPv4 路由表常把默认路由写成 0.0.0.0/0,IPv6 写成 ::/0。
默认网关只负责接过当前这一跳的包;它不会承诺远端服务可达,后续还要经过更多路由与策略检查。
在这里,我们需要区分两种作用范围不同的地址:IP 地址负责全局的、跨网络的端到端寻址;而*链路层地址(如 MAC 地址)只负责在当前这一跳的局域网内完成交付。在最常见的以太网(Ethernet)*中,网卡发送数据帧时,必须知道下一跳的 MAC 地址。对于 IPv4,主机会通过 ARP 协议来查询下一跳 IP 对应的 MAC 地址;而在 IPv6 中,则使用基于 ICMPv6 的邻居发现协议(NDP, Neighbor Discovery Protocol)。
IP 地址是什么?
IP 地址标识网络层接口,供 IP 数据报寻址和路由。它具有作用域和拓扑含义:同一接口可能同时拥有回环、链路本地、私有或公网等不同地址。
IP 地址标识的是网络层端点;具体应用还需结合传输协议和端口定位。
MAC 地址是什么?
MAC 地址是 Ethernet 等链路技术用来在本地链路交付帧的标识,常写成六组十六进制字节。它在每一跳都可能随着重新封装而变化,也可能由虚拟接口或系统随机生成。
路由器通常不会把远端主机的 MAC 原样跨互联网传播。
Ethernet 是什么?
Ethernet(以太网)是一族常见的局域网链路技术,定义帧格式、MAC 寻址和介质访问等规则。IP 数据报在 Ethernet 链路上传输时,会被装入 Ethernet 帧。
Wi-Fi、回环和隧道也能承载 IP,但它们的链路封装与 Ethernet 不完全相同。
ICMPv6 是什么?
ICMPv6 是 IPv6 的控制与错误报告协议,承载目标不可达、Packet Too Big、邻居发现和路由器发现等消息。它是 IPv6 正常运转的重要组成部分。
过度屏蔽 ICMPv6 可能破坏邻居发现或路径 MTU 探测,表现为连接超时和大包传输异常。
当你访问公网服务器时,你电脑发出的以太网帧,其目标 MAC 地址其实是你家的路由器或者公司的网关,而不是那台公网服务器的 MAC。数据包每经过一个路由器,链路层的首部都会被剥离并针对下一跳重新封装,而 IP 层的目标地址则始终不变,一直指向最终的服务器。
第四步:建立 TCP 连接
既然已经掌握了目标 IP 和端口,客户端就可以调用操作系统的 Socket 接口,正式发起 TCP 建连请求了。操作系统会为这次连接分配源 IP 和一个随机的临时源端口,然后向服务器发送 SYN 报文。双方通过经典的“三次握手”(SYN、SYN+ACK、ACK),协商好初始序列号(Sequence Number),以及 MSS(最大报文段长度)、窗口缩放(Window Scale)、SACK(选择性确认)等关键的 TCP 特性。
MSS 是什么?
MSS(Maximum Segment Size)表示一端愿意在单个 TCP 报文段中接收的最大 TCP 载荷长度,不包含 IP 和 TCP 首部。双方通常在 SYN 中各自通告自己的 MSS。
常见的 1460 来源于 Ethernet MTU 1500 减去 20 字节 IPv4 首部和 20 字节 TCP 首部;IPv6 或额外选项会改变实际计算。
在网络世界里,一条 TCP 连接可以由著名的“四元组”来唯一标识:
text
客户端 IP : 临时源端口 -> 服务器 IP : 443TCP 是一条全双工的通道,两端都有自己独立的发送和接收方向。三次握手一旦完成,客户端和服务端在内存里就建好了各自的状态机,准备好收发字节流了。关于三次握手中 Seq(序列号)和 Ack(确认号)的具体计算过程,我们会在第 15 章里拆解得清清楚楚。
第五步:在 TCP 之上建立 TLS
如果是 HTTPS,TCP 连接建好后还不算完,紧接着要在 TCP 的字节流之上进行 TLS 握手。在这个阶段,客户端和服务器会协商使用的 TLS 版本和密码套件(Cipher Suite),客户端还会验证服务器发来的证书(Certificate)是否合法可信。一旦双方确立了对称加密所需的会话密钥,后续所有的 HTTP 请求和响应,都会被严严实实地封装在加密的 *TLS 记录(TLS Record)*中传输。
TLS 版本是什么?
TLS 版本标识双方采用哪一代协议规则。现代部署主要使用 TLS 1.2 或 TLS 1.3;TLS 1.3 缩短了常规握手并移除了多种旧算法组合。
客户端和服务器需要拥有共同支持的版本,协商结果应从实际握手或端点日志确认。
密码套件是什么?
密码套件是一组用于保护连接的加密算法约定。TLS 1.2 的套件名称通常同时表达密钥交换、身份认证、对称加密和摘要;TLS 1.3 的套件主要指定对称加密与哈希,密钥交换和签名算法分开协商。
名称相似的套件可能具有不同安全属性,排障与安全审计都应记录完整协商结果。
TLS 证书是什么?
TLS 证书通常是 X.509 数字证书,把公钥与域名、组织等身份信息关联起来,并由签发者进行数字签名。客户端会检查有效期、名称、用途和信任链等条件。
证书证明的是公钥与身份之间的受信绑定;它不会单独保证服务器业务逻辑可靠。
会话密钥是什么?
会话密钥是连接双方通过握手导出的短期对称密钥材料,用于加密并验证 TLS 记录。对称加密速度快,适合保护大量应用数据。
它通常只在端点内存中存在;拥有服务器证书的公钥并不能直接解开现代 TLS 会话。
TLS Record 是什么?
TLS Record(TLS 记录)是 TLS 传输数据的封装单位,带有类型、版本兼容字段、长度和受保护内容。握手消息与应用数据都会被切分或组合进记录。
TLS Record、TCP 报文段和应用消息各有自己的边界,三者之间没有固定的一一对应关系。
此时如果有人在网络上抓包,他只能看到外层的 IP 头、TCP 头,以及 TLS 记录的长度、传输方向和时间戳。至于你请求了哪个具体的 HTTP 路径、带了什么 Header、传了什么 Body,都已经被加密保护起来了。在第 30 章里,我们会详细教大家如何区分应用层消息、TLS 记录以及底层 TCP 报文段(Segment)之间的边界。
第六步:交换 HTTP 请求与响应
等 TLS 安全通道就绪后,客户端终于可以把真正的 HTTP 请求字节流写入 TCP 连接了。服务端的 HTTP 组件(比如 Nginx 或 Tomcat)收到字节流后,解析出 HTTP 请求,交给后端的业务代码处理。处理完毕后,再把 HTTP 状态码、响应头和响应体(比如 HTML 文本)顺着原路写回到连接中。客户端读取这些响应字节,完成 HTTP 解析,页面就出来了。当然,浏览器解析 HTML 后,还会立刻去拉取里面引用的 CSS、JS、图片和字体,这就意味着会发起一波新的网络请求。
现代网络协议中,HTTP/1.1 会利用 Keep-Alive 机制复用同一条 TCP 连接来发送后续请求。HTTP/2 依然跑在 TCP 之上,但它引入了多路复用(Multiplexing),能在同一条连接里并发跑多条数据流。而最新的 HTTP/3 更是颠覆性地跑在了基于 UDP 的 QUIC 协议上。如果你直接拿浏览器去抓公网的包,很可能会同时看到这几种协议混杂在一起。为了避免一开始就陷入混乱,我们在本教程的首次外网实验中,会使用 curl 强制指定 HTTP/1.1 协议,让流量看起来最纯粹。
HTTP/1.1 是什么?
HTTP/1.1 使用文本形式的请求行和首部,并默认支持持久连接。一个连接上通常按顺序处理请求与响应;流水线机制部署有限,因此浏览器常并行建立多条连接。
HTTP/2 是什么?
HTTP/2 把 HTTP 消息编码为二进制帧,并让多个逻辑流复用同一条连接,同时提供首部压缩和流优先级等能力。它通常运行在 TLS over TCP 上。
同一 TCP 连接发生丢包时,依赖该连接的多个 HTTP/2 流都可能等待 TCP 恢复有序字节流。
多路复用是什么?
多路复用是在一条底层连接中交错承载多条独立逻辑流。每个 HTTP/2 帧带有流标识,接收端据此把交错数据还原给对应请求。
它提高连接利用率并减少重复握手,同时要求协议明确标识逻辑流和流内顺序。
HTTP/3 是什么?
HTTP/3 把 HTTP 语义映射到 QUIC,而 QUIC 运行在 UDP 之上并集成 TLS 1.3。不同 QUIC 流可独立处理丢包恢复,连接还可在网络地址变化后进行迁移。
UDP 是什么?
UDP(User Datagram Protocol,用户数据报协议)提供轻量、无连接的数据报传输,保留消息边界。它自身不保证送达、顺序或重传,应用可以按需求自行构建这些能力。
QUIC 选择 UDP 作为跨平台可部署的报文承载,并在用户态实现可靠性、拥塞控制和安全握手。
QUIC 是什么?
QUIC 是基于 UDP 的加密传输协议,集成 TLS 1.3、可靠流、多路复用、拥塞控制和连接迁移。HTTP/3 使用 QUIC 承载 HTTP 消息。
QUIC 的传输控制大多受加密保护,现场诊断通常更依赖端点日志、qlog 和密钥材料。
封装与解封装
在数据发送的过程中,网络栈的每一层都会把上一层交下来的数据当成自己的“载荷(Payload)”,并在前面加上本层专属的控制信息(也就是“首部”或“Header”),这个过程叫做封装。下面的嵌套图直观地展示了这种包裹关系:
text
HTTP 请求字节
└─ TLS 记录 (TLS Record)(HTTPS 场景)
└─ TCP 首部 + TCP 数据段 (Segment)
└─ IP 首部 + IP 数据报 (Datagram)
└─ 链路层首部 + 链路层载荷 + 尾部校验 (FCS)需要注意的是,各层的边界并不是严丝合缝的一一对应关系。一条巨大的 TLS 记录可能会被切分,跨越多个 TCP 报文段传输;反过来,一个 TCP 报文段也可能同时塞下了好几条微小的 TLS 记录。IP 层和链路层也都会根据各自的 *MTU(最大传输单元)*规则,去切分或封装它们当前的载荷。
MTU 是什么?
MTU(Maximum Transmission Unit)是某个网络接口或链路在单个网络层数据包中可承载的最大字节数。常见 Ethernet MTU 是 1500 字节,实际路径还可能因隧道、PPPoE 等封装而更小。
MTU 限制 IP 数据报大小;TCP 常结合路径 MTU 和双方 MSS 决定报文段载荷大小。
接收端的处理逻辑则刚好相反,是一个逐层“剥洋葱”的过程:网卡先接收链路上的以太网帧;IP 层剥离 IP 首部后,根据 IPv4 的 Protocol 字段或 IPv6 的 Next Header 字段,把载荷精准移交给 TCP;TCP 根据连接状态和序列号重组出有序的字节流;接着 TLS 层负责解密;最后 HTTP 层解析出真正的应用消息。
同一批数据在不同协议层有着不同的称呼:在应用层它是消息/请求,在 TCP 层变成了字节流和报文段 (Segment),在 IP 层被称为数据报 (Datagram),到了链路层则成了在网线里飞奔的帧 (Frame)。而且,根据你用的是 Wi-Fi、有线以太网还是本地回环地址(Loopback),最底层的帧格式也会有所区别。
四种标识各司其职
总结一下这几个关键标识符,它们各自负责不同范围的寻址:
| 标识符 | 解决的核心问题 | 常见的观察位置 |
|---|---|---|
| 域名 | 人和应用程序如何稳定、直观地引用服务 | URL、DNS 查询流量 |
| IP 地址 | 数据报在跨越整个互联网时,该送往哪台主机的哪个网卡 | IP 首部、系统的路由表 |
| MAC 地址 | 数据帧在当前这一小段局域网链路里,该扔给哪个确切的硬件(下一跳) | 以太网首部、ARP/NDP 邻居表 |
| TCP 端口 | 数据到达目标主机后,该交给哪个具体的应用程序进程(TCP 端点)处理 | TCP 首部、Socket 连接状态 |
在这个模型中,Socket(套接字)就是应用程序调用底层网络能力的系统接口。一条 TCP 连接建立后,操作系统内核里的这个已连接 Socket 对象,就牢牢绑定了本地 IP、本地端口、远端 IP、远端端口,以及当前连接的 TCP 状态。关于这点,我们在第 4 章会从操作系统的视角带大家深入探究。
动手实验:将 DNS、TCP 连接与 HTTP 请求对齐
纸上得来终觉浅。在这个实验里,我们将访问专用于文档示例的 example.com。
首先,打开 Wireshark,选择你正在上网的那张网卡开始抓包,并在上方输入显示过滤器(Display Filter):
text
dns || tcp.port == 443接着,打开 PowerShell 终端,依次运行下面这些命令:
powershell
# 强制查询 IPv4 地址
Resolve-DnsName example.com -Type A -DnsOnly
# 强制查询 IPv6 地址
Resolve-DnsName example.com -Type AAAA -DnsOnly
# 测试到目标 443 端口的连通性
Test-NetConnection example.com -Port 443 -InformationLevel Detailed
# 强制使用 HTTP/1.1 发起请求并打印详细日志
curl.exe --noproxy "*" --http1.1 -v https://example.com/ --output NUL
# 查看本机路由表
route print
# 查看本机邻居表(ARP/NDP 缓存)
Get-NetNeighbor | Sort-Object InterfaceIndex,IPAddress注:如果你在公司内网,可能需要配置显式代理(Proxy)。这种情况下,你的 TCP 实际连接目标其实是代理服务器的地址。注意观察 curl -v 吐出的日志,它会告诉你最终建立物理连接的真实 IP 是谁。而 Test-NetConnection 也会展示它在探测时选用的远端地址。
预期观察到的现象
执行完上述命令后,你应该能观察到以下现象:
Resolve-DnsName命令会返回一个或多个该域名的候选 IP 地址。Test-NetConnection会清晰地打印出你的本地源 IP、远端目标 IP、走的是哪张网卡,以及 443 端口到底通不通。- 在
curl的详细输出中,你可以清楚地看到建连过程:先建立 TCP 连接,然后是 TLS 握手信息,接着才是 HTTP 请求行和最终的 HTTP 响应状态码。 - 切回 Wireshark,你能完整抓到 TCP 三次握手、TLS 密钥交换、一堆标着“Application Data”的加密报文,以及最后的连接挥手关闭过程。
- 查看邻居表时,你会发现里面映射的 MAC 地址基本都是你所在局域网的设备(比如你家路由器或同网段的电脑)。你绝对不可能在里面直接找到
example.com这台远在天边的服务器的 MAC 地址。
有时候,你在 Wireshark 里可能抓不到 DNS 查询报文,这通常是被本地缓存截胡了,或者是你开启了加密 DNS(DoH/DoT),亦或是流量被 VPN 接管了。遇到这种情况不要慌,把这些偏差记录下来也是实验的一部分。你可以通过比对 Resolve-DnsName 的结果和 curl 日志里实际连接的 IP 来补齐“证据链”。另外,我们在 curl 中加的 --http1.1 参数,非常关键地把应用层协议锁死在了基于 TCP 的传统 HTTP/1.1 上,排除了 HTTP/2 或 HTTP/3 的干扰。
DoH 是什么?
DoH(DNS over HTTPS)把 DNS 查询封装进 HTTPS 流量,通常使用 TCP/TLS 或 HTTP/3。它能保护查询内容免受路径上的明文观察和篡改,但普通 dns 抓包过滤器也因此无法直接识别查询名称。
DoT 是什么?
DoT(DNS over TLS)通过专用 TLS 连接传输 DNS,常用 TCP 853 端口。其加密目标与 DoH 相似,流量形态和端口更容易与普通 HTTPS 区分。
VPN 是什么?
VPN(Virtual Private Network,虚拟专用网络)通过隧道接口把选定流量封装并送往另一网络端点。启用后,本机路由、DNS 服务器、源 IP 和可见抓包接口都可能变化。
排障时应确认流量是在隧道封装前、封装后还是 VPN 对端被捕获。
协议模型的适用条件
需要说明的是,本章为了方便大家理解,是基于**“首次访问且必须新建连接”**这一最基础的线性模型来讲解的。但在真实的浏览器环境里,情况要复杂得多。浏览器为了极致的性能,会频繁使用 DNS 缓存、TCP 连接池、TLS 会话恢复(Session Resumption)等手段;网络架构上也会涉及正向代理、CDN 边缘节点;在连接策略上还会采用像 Happy Eyeballs(并发尝试 IPv4 和 IPv6,谁快用谁)这样的算法。甚至,它可能直接选择 HTTP/3。
TCP 连接池是什么?
TCP 连接池保存一组可复用的已连接 Socket,让新请求优先借用现成连接,减少建连、TLS 握手和慢启动成本。连接池通常按目标、协议、安全上下文和代理配置等条件分组。
池内连接也会过期、失效或被中间设备回收,借出前后仍需正确处理读写错误和超时。
TLS 会话恢复是什么?
TLS 会话恢复让客户端和服务器基于先前会话产生的票据或预共享密钥恢复安全上下文,从而减少握手计算与往返。TLS 1.3 常使用 NewSessionTicket 提供恢复凭据。
恢复的是 TLS 安全会话信息;底层 TCP 或 QUIC 连接仍可能是新建的。
正向代理是什么?
正向代理代表客户端访问外部服务。客户端先连接代理,再由代理连接目标;HTTPS 常通过 CONNECT 建立隧道,也可能由受控代理终止 TLS 并重新发起后端连接。
因此,客户端抓包中直接对端可能是代理 IP,目标域名与最终后端需要结合代理日志和应用协议确认。
CDN 边缘节点是什么?
CDN 边缘节点是靠近用户部署的缓存或反向代理入口。它可以直接返回缓存内容,也可以代表用户回源获取数据。
客户端到边缘和边缘到源站通常是两段独立连接,二者的地址、RTT、TLS 会话和 TCP 状态各自独立。
Happy Eyeballs 是什么?
Happy Eyeballs 是双栈客户端在 IPv6 与 IPv4 候选地址之间进行快速竞争和回退的连接算法。客户端通常先尝试较优候选,并在短暂延迟后启动另一地址族的尝试,以减少某一条路径失效带来的等待。
一次用户访问因此可能产生多次重叠的建连尝试,抓包分析应确认最终胜出的地址和被取消的连接。
所以在做排障或现场分析时,我们的首要任务是先抓准:这次请求实际连的是哪个远端 IP?用的是什么底层传输协议?是不是复用了老连接? 摸清这些核心线索后,再把观察到的现象套用到相应的网络模型中去。
如果你对底层的链路层知识意犹未尽,可以去阅读 Frame、MAC、IP 与 ARP;如果想了解更多关于 Socket 的概念,可以参考 Socket 与 WebSocket。
理解检查
- URL 中的哪一部分会参与 DNS 查询?又是哪一部分通常决定了目标端口?
- 当你访问一台公网服务器时,你电脑发出的以太网帧,其目标 MAC 地址通常是谁的?
- 操作系统的路由表主要负责确定哪三项关键的发送信息?
- 为什么对 HTTPS 流量进行抓包时,我们依然能把 TCP 首部看得一清二楚,却无法直接读取 HTTP 的正文?
- 如果抓包文件里死活找不到 DNS 查询报文,你可以通过哪些侧面证据来确认客户端最终连接的目标地址?
本章小结
一次看似简单的网络请求,实际上是一条逐层收敛、步步为营的探索路径:URL 表达了应用层的访问意图,DNS 将其转化为候选的 IP 地址,路由表负责决定出口网卡和下一跳的方向,ARP 或 IPv6 ND 则锁定了当前物理链路上的具体硬件。在这条打通的路径上,TCP 负责建立可靠的双向字节流,TLS 为这层通信披上加密的铠甲,最后,HTTP 在这个安全的通道里完成一问一答的业务交互。
域名、IP、MAC 和端口,它们各司其职,服务于不同范围的寻址需求。只有当这四个标识完美配合,一串串数据字节才能毫发无损地抵达正确的应用程序。
在下一章中,我们将把聚光灯打在 TCP 层上,重点探讨它是如何在一个随时可能丢包、乱序和拥塞的糟糕 IP 网络环境中,硬生生维护出一条绝对有序且可靠的字节流的。