网络基础知识第 2 部分:传输层与 TLS
最后更新:September 11, 2026
这是一个由四部分组成的系列
第 1 部分:分层模型、链路层与路由层 · 第 2 部分:传输层与 TLS (本文档) · 第 3 部分:应用层协议 · 第 4 部分:一次请求的旅程与云
第 1 部分介绍了如何将数据包送达目标主机。本部分将比较可靠的流传输(TCP 和 QUIC)与 UDP 数据报,然后讲解 TLS 如何保护通信。UDP 本身不提供可靠性或 TLS;应用会选择适当的安全协议(如 DTLS),或者使用集成了 TLS 1.3 的传输协议(如 QUIC)。
这张图概括了本部分的核心内容:
3. 传输层:端到端交付
从这里开始,你的对话对象不再是“网络”,而是“进程”。这就是端口号会出现的原因。
TCP
定义: 面向连接的传输协议,提供可靠、有序的字节流。
工作原理: 通过三次握手(SYN → SYN+ACK → ACK)建立连接。序列号保证顺序,ACK 和重传用于恢复丢失的数据,滑动窗口控制流量,拥塞控制则根据网络负载进行调整。对于应用来说,TCP 提供了一种简洁的抽象:一个无间隙的字节流。
实际应用: 有序交付会造成队头阻塞(HOL):缺失的 TCP 段会阻止间隙之后的字节被交付。使用 HTTP/2 时,这可能会延迟共享该连接的多个流;已交付的数据和独立的应用工作仍可继续处理。QUIC 消除了这种特定的跨流传输层排序依赖。
对于没有经过优化的典型新建连接,TCP 建连约需 1 个 RTT,随后完整的 TLS 1.3 握手需 1 个 RTT(TLS 1.2 通常共需 2 个 RTT)。连接复用、会话恢复、早期数据和 TCP Fast Open 会改变时序;重试则可能增加延迟。应结合实际工作负载评估连接池。
拥塞控制简史: 除了带宽、延迟、缓冲区和应用行为外,拥塞控制也会影响吞吐量。经典的 Reno 会在发生丢包时缩小拥塞窗口。CUBIC 是 Linux 中常见的默认算法,它使用立方窗口增长函数来提高高带宽路径上的可扩展性。BBR 会对瓶颈带宽和传播 RTT 建模,以指导发送;其对丢包和 ECN 的使用也取决于具体实现和版本。任何算法都无法保证在所有长距离或移动网络路径上提高吞吐量。sysctl net.ipv4.tcp_congestion_control 只会读取已配置的默认值;更改默认值会影响新建连接,并且需要单独配置和测量。
TIME_WAIT 与端口耗尽: 在正常的优雅关闭中,主动关闭连接的一方通常会进入 TIME_WAIT;同时关闭时,双方都可能进入该状态。连接频繁创建和关闭可能导致可用连接元组、临时端口或 NAT 映射耗尽,具体取决于实现和目标端模式。TIME_WAIT 条目并非总会为所有远端端点保留该端口。更改内核设置之前,应先诊断实际限制并考虑复用连接;TIME_WAIT 还有助于防止旧连接的延迟数据包造成影响。
UDP
定义: 一种精简的传输协议,无需建立连接即可发送数据报。
工作原理: 8 字节的报头仅包含源端口、目标端口、长度和校验和。没有握手、没有重传、没有排序,也没有拥塞控制。它本质上就是“带端口号的 IP”。
实际应用: 实时应用可能更倾向于及时交付,而不是重传过时的数据;DNS 通常也使用 UDP 进行小型数据交换。应用必须自行实现所需的可靠性和适当的拥塞控制,或者使用 QUIC 这类提供这些功能的协议。
需要注意的是,无状态特性使 UDP 容易遭受 IP 欺骗和放大攻击。向外部开放 UDP 服务时,应规划响应大小限制和请求速率控制。
QUIC
定义: 一种构建在 UDP 之上的安全多路复用传输协议。
工作原理: QUIC 基于 UDP 从头重新设计了 TCP+TLS 过去负责的一切。它有四个关键特性:
- 独立的流交付:每个流都有自己的字节顺序,因此一个流上的丢包不一定会阻止另一个流中可用数据的交付。数据包恢复和拥塞控制仍会跨连接或路径运行;流可能会因自身缺失的字节而阻塞,应用或 HTTP/3 QPACK 依赖也可能造成阻塞。
- 内置加密:QUIC 集成了 TLS 1.3 握手,并使用自己的数据包保护机制,而不是 TLS 记录。正常的完整握手约需 1 个 RTT。符合条件且获准的会话恢复可以携带 0-RTT 早期数据,但握手仍会在之后完成;Retry 或额外的握手交互可能增加延迟。
- 连接 ID:在端点支持并通过路径验证的情况下,连接 ID 可让连接在地址变更后继续保持。迁移限制或路径不可用仍可能中断从 Wi-Fi 切换到蜂窝网络的过程;连接连续性并无保证。
- 实现灵活性:QUIC 通常在用户空间实现,因此传输层变更可以随应用或库一起发布。用户空间实现并非协议要求。
实际应用: HTTP/3 通常使用 UDP 443。如果该路径被阻断,只要服务器支持,HTTP 客户端可以尝试通过 TCP 使用 HTTP/2 或 HTTP/1.1;QUIC 本身不会转换成 TCP。在将性能结果归因于 QUIC 之前,应检查可达性、协商出的协议以及实现或卸载行为。CPU 开销取决于具体实现和工作负载。
需要注意的一项安全问题是:0-RTT 数据可能被重放。 重放早期数据交换可能导致应用多次处理同一个请求;仅靠传输层数据包去重并不能提供应用层重放保护。只允许应用明确评估为可安全重放的操作。仅仅使用 GET 方法名或声称操作幂等,并不足以证明安全。服务器可以拒绝早期数据;HTTP 服务器可以使用 425 Too Early,让客户端在握手完成后重试。应在客户端、CDN 和源站之间统一配置此策略。
4. 安全性:TLS
TLS
定义: 为传输中的数据提供机密性、完整性和身份验证的协议。
工作原理: TLS 在握手期间协商加密参数并建立密钥。基于证书的握手通过证书和密钥持有证明来验证服务器身份;基于 PSK 的握手则可以使用先前建立或通过外部配置的密钥进行身份验证。TLS 记录用于保护应用数据。TLS 1.3 使用经过身份验证的加密(AEAD)来提供机密性和完整性。
正常的完整 TLS 1.3 握手约需 1 个 RTT;会话恢复允许在满足额外条件时选择性地发送早期数据。TLS 1.3 移除了静态 RSA 密钥交换和旧版密码套件,但仍支持 RSA 证书签名。临时(EC)DHE 密钥交换可提供前向保密,包括与 PSK 结合使用时。仅使用 PSK 的密钥交换和 0-RTT 数据无法提供同等的前向保密保证。
实际应用: 以下三个问题反复出现。
- 证书过期:自动续期,并单独监控证书过期时间和证书是否成功部署。
- SNI 暴露:仅使用 TLS 1.3 并不能隐藏 ClientHello 中的 SNI。在双方均支持并完成配置时,ECH(加密 Client Hello,RFC 9849)可以保护内部 ClientHello。QUIC Initial 数据包的密钥可公开推导,因此仅靠 Initial 加密无法隐藏 SNI。ECH 也不会隐藏目标 IP 或所有流量元数据。
- 终止点设计:记录每一跳:客户端到负载均衡器、负载均衡器到应用,以及任何服务到服务的连接。TLS 终止并不会自动加密下一跳。必要时应在该跳使用 TLS;如果双方都必须通过证书进行身份验证,则使用 mTLS。服务网格可以自动化这一过程,但并非每种设计都需要服务网格。
证书链与 OCSP 装订: 典型的 X.509 验证会从叶证书出发,经过所需的中间证书,构建到已配置的信任锚的路径。服务器应发送所需的中间证书;根证书通常已由客户端信任。缺少中间证书可能导致因客户端而异的故障,不过并非每条有效证书链都包含中间证书。吊销处理方式取决于颁发者和客户端。在支持 OCSP 的情况下,OCSP 装订允许服务器附带经过签名的状态响应,并可减少客户端直接查询。不过,这并非通用做法:Let’s Encrypt 已于 2025 年 8 月停止 OCSP 服务,转而使用 CRL。应根据实际 CA 和客户端选择匹配的证书及吊销配置。
📎 关于 Istio 如何实现自动化,请参阅 Istio mTLS。
主要参考资料:TLS 1.3、QUIC 传输协议、QUIC/TLS、HTTP 早期数据、ECH、Linux TCP 设置、Let’s Encrypt OCSP 服务终止说明。
下一篇:第 3 部分:应用层协议
