网络
网络层协议
网络层的核心职责是把数据包从源主机跨网络送达目的主机,围绕三件事展开:编址(IP)、地址解析(ARP)、私网与公网互通(NAT)。
IP 地址分类
IP 地址按首几位划分地址类别,类别决定单个网络可容纳的主机数量:
| 类别 | 范围 | 说明 |
|---|---|---|
| A 类 | 0.0.0.0-127.255.255.255 | 单体网络 |
| B 类 | 128.0.0.0-191.255.255.255 | 中型网络 |
| C 类 | 192.0.0.0-223.255.255.255 | 小型网络 |
| D 类 | 224.0.0.0-239.255.255.255 | 多播地址 |
| E 类 | 240.0.0.0-255.255.255.255 | 保留 |
IPv4 地址为 32 位,已接近耗尽;IPv6 把地址扩展到 128 位,两者在过渡期共存,这也是 NAT 和 CIDR 被广泛使用的原因。
CIDR 与私有地址段
分类编址粒度僵硬、浪费地址,实际使用 CIDR(无分类编址):用斜线记法如 192.168.1.0/24,斜线后的数字是网络前缀长度,可以按任意长度划分子网。
以下三个地址段为私有地址,只能在内网使用,出网必须经过 NAT 转换:
| 地址段 | 可用主机数 | 常见场景 |
|---|---|---|
| 10.0.0.0/8 | 约 1677 万 | 大型企业内网 |
| 172.16.0.0/12 | 约 104 万 | 中型网络 |
| 192.168.0.0/16 | 约 6.5 万 | 家庭/小型办公网络 |
划分子网
划分子网的目的是把已分配的网络进一步划分为多个较小的网络:隔离广播域、便于管理,且不额外消耗地址块。
机制是从主机号 host-id 借用若干个比特作为子网号 subnet-id,地址结构变为"网络号 + 子网号 + 主机号"三段;子网掩码用于区分网络部分与主机部分:网络号和子网号都为 1,主机号为 0。
借用的比特数决定划分粒度:借 n 位可分出 2n 个子网;剩余 m 位主机号时,每个子网有 2m - 2 个可用主机(扣除全 0 的网络地址和全 1 的广播地址)。
以把 192.168.1.0/24 划分为 /26(借 2 位)为例,得到 4 个子网:
| 子网 | 网络地址 | 可用主机范围 |
|---|---|---|
| 1 | 192.168.1.0/26 | 192.168.1.1 - 192.168.1.62 |
| 2 | 192.168.1.64/26 | 192.168.1.65 - 192.168.1.126 |
| 3 | 192.168.1.128/26 | 192.168.1.129 - 192.168.1.190 |
| 4 | 192.168.1.192/26 | 192.168.1.193 - 192.168.1.254 |
划分子网与 CIDR 是同一件事的两面:CIDR 的斜线记法(如 /26)正是子网借用后前缀总长度的表达方式。
ARP 协议
ARP 协议完成 IP 地址与物理地址的映射。之所以需要它,是因为 IP 层只知道逻辑地址,而局域网内帧的实际传输必须依赖物理地址。
查询过程分三步:
- 广播请求:源主机广播 ARP 请求,询问"这个 IP 是谁"
- 单播回复:目标主机收到后,单播回复自己的物理地址
- 缓存命中:每个主机都设有 ARP 高速缓存,保存局域网内各主机和路由器的 IP 到硬件地址的映射表,命中缓存即可避免重复广播查询
NAT
NAT 解决 IPv4 地址不足与内网主机访问因特网的双重问题:内网主机使用私有地址,出网时由 NAT 路由器将其转换为全球 IP 地址。
转换方式分两种:
- 静态转换:私网地址与公网地址一对一固定映射,适合需要对外暴露的内网服务器
- 动态转换:出网时从公网地址池临时借用一个地址,用完归还
而今天普遍使用的是进一步演进的 NAPT(网络地址端口转换):在地址转换之外再加一层端口映射,多台内网主机共用一个公网 IP,靠不同的源端口区分会话——整个家庭网络用一个公网地址上网,靠的就是它。
传输层协议
传输层提供进程到进程的通信:网络层只负责把数据包送到主机,传输层通过端口号把数据交给正确的进程。两大协议 TCP 与 UDP 代表可靠性与性能的两种取舍。
TCP 与 UDP 对比
| 对比项 | TCP | UDP |
|---|---|---|
| 连接 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 可靠交付:序号、确认、重传 | 尽最大努力交付,不保证 |
| 传输单位 | 字节流(报文段) | 报文 |
| 流量/拥塞控制 | 有 | 无 |
| 首部开销 | 20 字节起 | 8 字节 |
| 典型场景 | HTTP/1.1 与 HTTP/2、文件传输 | DNS 查询、直播、QUIC |
直播、视频通话选 UDP 而非 TCP:丢一帧只是画面瑕疵,等重传反而造成卡顿,实时性比完整性更重要。
三次握手与四次挥手
三次握手的目的有两个:确认双方的收发能力都正常,并同步双方的初始序号。
两次握手不够:服务端无法确认客户端的接收能力正常,且客户端超时的旧连接请求到达后,服务端会白白建立连接浪费资源。
四次挥手释放连接:
FIN → ACK → FIN → ACK 的顺序之所以比三次握手多一次,是因为 TCP 是全双工的,收到 FIN 的一方可能还有数据要发,先回 ACK 等数据发完再发自己的 FIN。
可靠传输机制
TCP 的可靠交付由四个机制共同保证:
| 机制 | 解决的问题 |
|---|---|
| 序号 + 确认应答 | 按序重组、发现丢包 |
| 超时重传 | 丢包后自动补发 |
| 流量控制(滑动窗口) | 接收方处理不过来时让发送方减速 |
| 拥塞控制(慢开始、拥塞避免、快重传、快恢复) | 网络拥堵时主动降速,避免雪崩 |
流量控制保护的是接收方,拥塞控制保护的是网络链路,两者缺一不可。拥塞控制的四个阶段合起来是一个循环节奏:
慢开始从小窗口起指数探测可用带宽,到达阈值后转拥塞避免线性缓增;丢包则触发快重传、快恢复把窗口折半后重新爬升——网络拥堵时主动降速,避免雪崩。
DNS 域名解析
DNS 把域名解析为 IP 地址:人擅长记域名,路由器只认 IP,DNS 是两者之间的翻译层。
解析按缓存逐级查找,命中即返回:
- 浏览器缓存 → 操作系统缓存(含 hosts 文件)
- 本地 DNS 服务器(运营商或公共 DNS 如 8.8.8.8)
- 本地 DNS 无缓存时,向根域名服务器 → 顶级域名服务器 → 权威域名服务器逐级查询
本地 DNS 向根/顶级/权威服务器的查询是迭代查询(每一级只告诉下一级的地址),本地 DNS 替客户端跑完全程,对客户端而言是递归查询。
各级缓存按记录的 TTL 过期,这也是改 DNS 记录后全球生效有延迟的原因。记录类型、邮件认证与 Cloudflare 代理模式的实践整理见 DNS。
HTTP 各版本
HTTP 的演进主线是不断解决队头阻塞、提升连接利用率。
队头阻塞指消息排队传输时,排在最前面的消息还没处理完(等丢包重传、体积未传完等),后面所有消息都只能跟着等、无法先送达。它出现在两个层面:HTTP/1.1 层面,同一连接上的多个请求只能按序应答,第一个响应慢,后续响应一起被卡住;TCP 层面,任何一个报文段丢失,这条连接上后续所有数据都要等它重传完成,哪怕两者毫无关系。下表可以读作对这两层队头阻塞的交替解决:
| 版本 | 主要特性 |
|---|---|
| HTTP 0.9 | 仅支持纯文本数据传输,仅支持 GET 请求方式,无状态,短连接 |
| HTTP 1.0 | 支持 POST、GET、HEAD 三种方法,支持长连接(但默认还是使用短连接) |
| HTTP 1.1 | 新增 PUT、DELETE、CONNECT、TRACE、OPTIONS 方法;默认使用长连接;存在的问题:队头阻塞 |
| HTTP 2.0 | 二进制分帧;多路复用(解决了 1.1 版本中的队头阻塞问题);头部压缩 |
| HTTP 3.0 | 基于 UDP 的 QUIC 多路复用;0RTT 建链 |
多路复用
HTTP/2 的多路复用允许同时在一个连接上并行传输多个请求和响应,解决了 HTTP/1.1 应用层的队头阻塞问题;但 TCP 层的队头阻塞依然存在,这正是 HTTP/3 改用基于 UDP 的 QUIC 的原因。
HTTP 也是许多应用层协议的地基:WebSocket 通过 HTTP 握手升级为全双工通道,详见 WebSocket;gRPC 基于 HTTP/2 实现,代理要支持它本质上是支持 HTTP/2 的多路复用与长连接。
HTTPS 与 TLS
HTTP 明文传输存在三个风险:被窃听、被篡改、被冒充。HTTPS = HTTP + TLS,分别用加密、完整性校验、身份认证解决这三个问题。
证书与 CA:服务端把公钥交给 CA 签发成证书,客户端用内置的 CA 根证书逐级验证证书链。这解决了"公钥属于谁"的信任问题,防止中间人拿自己的公钥冒充服务端。
TLS 握手:用非对称加密协商出一把对称密钥,之后通信全用对称加密。这样设计是因为对称加密快但密钥没法安全传递,非对称加密能安全传递密钥但慢,两者配合各取所长。TLS 1.3 将握手简化为 1-RTT,复用会话时可做到 0-RTT。
0-RTT 重放风险
0-RTT 携带的数据没有防重放保护,幂等的读请求无影响,写请求需要服务端自行做重放防护。
TLS 版本选择:1.0/1.1 有已知漏洞且已被主流浏览器废弃,服务端应至少要求 1.2,优先启用 1.3。
HTTPS 安全机制
HTTPS 的安全性不只靠证书,还需要一组扩展机制防止降级、篡改与混合内容。
HSTS
HSTS(HTTP 严格传输安全)通过 Strict-Transport-Security 响应头告知浏览器此后只用 https 访问该域名。它防的是 SSL 剥离:攻击者篡改明文 http 请求的响应,把站点的 https 链接降级成 http,用户不知不觉就一直在明文通信;浏览器一旦记住只用 https,这类降级攻击就不再奏效。注意它有"粘性":一旦下发 max-age,浏览器在有效期内拒绝 http 访问,启用前必须确认全站 https 已稳定,稳妥做法是先小 max-age 试运行再逐步加长。
机会加密
机会加密是 http 向 https 过渡期的兼容手段:站点暂时无法全站 https 时,先把明文链路升级为加密传输,解决被动窃听问题。
它的机制是 HTTP 替代服务(Alt-Svc):服务端在 http 响应头中声明一个替代服务,浏览器收到后把后续请求改走该服务——链路用 TLS 加密并运行 HTTP/2,但不验证服务端证书。
"机会"二字正来自它的安全边界:不验证证书意味着只能防被动窃听,防不住主动的中间人攻击(攻击者可以伪造替代服务声明劫持连接),所以地址栏仍显示 http、没有安全锁。能部署证书的站点应直接使用 https 配合 HSTS,机会加密只是"先加密、后认证"的过渡方案。
混合内容
https 页面引用 http 资源称为混合内容:此时加密通道只保护了主文档,子资源仍走明文链路,攻击者可以篡改这些资源间接控制整个页面,所以浏览器会警告或拦截。
浏览器按资源风险分两档处置:
| 类型 | 典型资源 | 处置 |
|---|---|---|
| 主动混合内容 | <script>、<iframe>、CSS、fetch/XHR | 严格拦截 |
| 被动混合内容 | <img>、音频、视频 | 早期浏览器仅警告;现代浏览器自动升级为 https,升级失败则拦截 |
分档的原因:主动资源能执行代码、改变页面行为,被篡改等于把整个页面交给攻击者,必须拦截;被动资源只负责展示、不参与页面逻辑,处置从宽。
修复分两层:
- 治本:把资源链接全部改为 https(或用相对路径),静态站点可用工具自动改写页面内的 http 链接
- 兼容过渡:在响应头声明 CSP
upgrade-insecure-requests,浏览器会自动把页面内的 http 子资源请求升级为 https,适合暂时无法逐个改写页面的场景
代理层与源站
引入反向代理/CDN 后,链路拆成浏览器↔代理和代理↔源站两段,两段的安全策略独立配置,问题往往出在衔接处。代理侧的边缘缓存见 缓存,DDoS/Bot 等流量防护见 流量安全。
回源链路的加密
代理到源站这段链路有三种策略:
- 明文:源站无证书,最简单但无任何保护
- 加密但不验证源站证书:源站用自签名证书,防窃听但不防冒充
- 加密且验证证书有效性:源站持有有效证书,推荐
策略选错最典型的事故是重定向循环:代理用 http 回源,源站又强制 http→https 跳转,两边互相重定向,浏览器报 ERR_TOO_MANY_REDIRECTS。解法是让代理回源协议与源站的跳转策略保持一致。
获取真实客户端 IP
经过代理后,源站看到的源地址是代理的 IP,真实客户端 IP 需要靠请求头传递:
- X-Forwarded-For:标准做法,每级代理追加上一跳地址,如
X-Forwarded-For: 203.0.113.7, 10.0.0.1, 10.0.0.2,最左侧是真实客户端 - CDN 专用头:CDN 通常另提供专用头直接给出客户端 IP(如 Cloudflare 的 CF-Connecting-IP),无需自己解析
这些头可以被客户端伪造
请求不经代理、或代理不重写该头时,客户端可以填任意值;源站只能信任由可信代理写入的值。
HTTP 扩展与页面加载
HTTP 协议层有多个直接服务于页面加载速度的扩展。
Early Hints(103)
服务端先发送 103 临时响应,用 Link 头告知关键资源地址,浏览器在最终 200 响应到达前就开始预加载,缩短首屏时间。
推测性预取
通过 Speculation Rules API 等机制声明式地告知浏览器提前预取下一页资源,用户真正跳转时直接命中。
脚本延迟执行
JavaScript 阻塞渲染,把非关键脚本推迟到页面解析完成后执行,可缩短首次绘制时间。具体用 defer 和 async 属性:defer 在 HTML 解析完成后按顺序执行;async 下载完立即执行、不保证顺序,适合统计脚本这类互不依赖的脚本。
第三方资源自托管
把字体等第三方资源托管到自己的域名或 CDN,既减少外部请求,也避免第三方借加载时机追踪用户。
输入 URL 后发生了什么
一次 HTTPS 访问把以上所有知识串成一条链路:
- DNS 解析:域名逐级查缓存、查 DNS 服务器,拿到目标 IP
- TCP 三次握手:与目标 IP 的 443 端口建立连接
- TLS 握手:验证证书链,协商出对称密钥
- 发送 HTTP 请求:之后的报文都在加密信道里传输
- 响应与渲染:浏览器解析响应,渲染页面
- 连接释放:空闲超时后四次挥手;开启 keep-alive 时连接可被后续请求复用