diff --git a/content/posts/2023-04-11-xray-reality.md b/content/posts/2023-04-11-xray-reality.md index 260def0..82adbaa 100644 --- a/content/posts/2023-04-11-xray-reality.md +++ b/content/posts/2023-04-11-xray-reality.md @@ -5,13 +5,13 @@ lastmod: 2026-05-03 slug: xray-reality tags: ["TLS", "Xray", "VLESS", "Reality", "X25519", "代理协议"] categories: ["网络协议"] -description: "REALITY 协议通过 TLS 1.3 key_share 字段嵌入身份标记 + 主动探测时透明回放真站,从协议层消除 TLS 指纹特征。本文从协议设计到服务端 / 客户端完整搭建。" +description: "REALITY 协议通过 TLS 1.3 key_share 字段嵌入身份标记 + 主动探测时透明回放真站,从协议层消除 TLS 指纹特征。本文从协议设计到服务端 / 客户端完整搭建。" draft: false --- -> 整理自 [bandwh.com](https://www.bandwh.com/net/994.html)(原文 2023-04-11),本文于 2026-05 重新整理发布。 -> 适用系统:Debian 11 | Xray 版本:>= 1.8.0 -> 文中所有 UUID / X25519 密钥均为示例值,实际部署务必使用 `xray uuid` / `xray x25519` 重新生成。 +> 整理自 [bandwh.com](https://www.bandwh.com/net/994.html)(原文 2023-04-11),本文于 2026-05 重新整理发布。 +> 适用系统:Debian 11 | Xray 版本:>= 1.8.0 +> 文中所有 UUID / X25519 密钥均为示例值,实际部署务必使用 `xray uuid` / `xray x25519` 重新生成。 --- @@ -19,7 +19,7 @@ draft: false ### 1.1 为什么需要 Reality? -传统 v2ray 方案需要购买域名并生成 TLS 证书,通过各种流量伪装来规避检测。然而随着 DPI 检测能力的升级,**v2ray 的 TLS/XTLS 协议特征已可被精准识别**,导致 VPS 的 443 端口频繁被封锁或阻断。 +传统 v2ray 方案需要购买域名并生成 TLS 证书,通过各种流量伪装来规避检测。然而随着 DPI 检测能力的升级,**v2ray 的 TLS/XTLS 协议特征已可被精准识别**,导致 VPS 的 443 端口频繁被封锁或阻断。 Xray 1.8.0 版本推出了全新的 **REALITY 协议**,配合此前的 **Vision 流控**,组成了当前最新的协议组合: ``` @@ -34,7 +34,7 @@ VLESS + Vision + uTLS + REALITY | 前向保密 | 仍保有 TLS 前向保密性,历史流量无法被解密 | | 抗证书链攻击 | 证书链攻击无效,安全性超越常规 TLS | | 无需域名 | 指向他人网站的 SNI,无需自己购买域名或配置 TLS | -| 中间人防御 | 即使客户端配置泄露,审查方也无法进行有效中间人攻击 | +| 中间人防御 | 即使客户端配置泄露,审查方也无法进行有效中间人攻击 | | SNI 阻断消失 | 据实测,使用 Reality 后 SNI 阻断现象消失 | ### 1.3 使用前提 @@ -42,7 +42,7 @@ VLESS + Vision + uTLS + REALITY - 一台可访问的 VPS(无需域名) - 服务端与客户端 **Xray 均需 >= 1.8.0 版本** - 443 端口不被 Nginx、Caddy 等其他程序占用 -- **不支持 CDN 代理**(如 Cloudflare 橙云,会终止 TLS 让 Reality 的端到端伪装失效)。CF **灰云(DNS only)** 只做 DNS 解析、不接管流量,等价于直连 VPS,可正常使用 +- **不支持 CDN 代理**(如 Cloudflare 橙云,会终止 TLS 让 Reality 的端到端伪装失效)。CF **灰云(DNS only)** 只做 DNS 解析、不接管流量,等价于直连 VPS,可正常使用 官方 GitHub:https://github.com/XTLS/REALITY @@ -237,13 +237,13 @@ wget --no-check-certificate https://github.com/teddysun/across/raw/master/bbr.sh ### 5.1 为什么使用公私钥而非仅 UUID? -传统方案若使用对称密钥(UUID),攻击者一旦获取客户端配置,即可实施中间人攻击。 +传统方案若使用对称密钥(UUID),攻击者一旦获取客户端配置,即可实施中间人攻击。 REALITY 使用 **X25519 非对称密钥 + TLSv1.3 key_share** 机制: -- 即使攻击者获取到客户端公钥,也**无法验证某条连接是否属于 REALITY** +- 即使攻击者获取到客户端公钥,也**无法验证某条连接是否属于 REALITY** - 更无法进行有效的中间人攻击 -> REALITY 的设计原则是:**默认假设客户端配置已泄露**,将安全边界收敛至服务端私钥。只要服务端私钥不泄露,流量就是安全的。即使私钥泄露,攻击者也无法直接解密历史流量(前向保密),只能尝试中间人攻击,但中间人需要持有 Reality 私钥才能伪装服务端,这做不到。 +> REALITY 的设计原则是:**默认假设客户端配置已泄露**,将安全边界收敛至服务端私钥。只要服务端私钥不泄露,流量就是安全的。即使私钥泄露,攻击者也无法直接解密历史流量(前向保密),只能尝试中间人攻击,但中间人需要持有 Reality 私钥才能伪装服务端,这做不到。 建议:**定期更换公私钥对**,公钥可在多个客户端间安全共享。 diff --git a/content/posts/2026-04-30-https-journey.md b/content/posts/2026-04-30-https-journey.md index ae51801..2fe8b3d 100644 --- a/content/posts/2026-04-30-https-journey.md +++ b/content/posts/2026-04-30-https-journey.md @@ -4,66 +4,66 @@ date: 2026-04-30 slug: https-journey tags: ["HTTPS", "TLS", "网络", "密码学", "GFW", "科普", "Reality"] categories: ["科普"] -description: "从指尖按下屏幕,到电子在硅里隧穿、电磁波在空中传播、光子在光纤里复制、数据在海底跨洋、密钥在素数空间里暗藏——一篇关于一次 HTTPS 请求背后整条链路的科普长文。" +description: "从指尖按下屏幕,到电子在硅里隧穿、电磁波在空中传播、光子在光纤里复制、数据在海底跨洋、密钥在素数空间里暗藏——一篇关于一次 HTTPS 请求背后整条链路的科普长文。" draft: false --- -> 一篇关于"按一下手机搜索按钮,到看到结果之间这不到一秒钟,世界上发生了什么"的科普长文。 +> 一篇关于"按一下手机搜索按钮,到看到结果之间这不到一秒钟,世界上发生了什么"的科普长文。 > -> 顺着一个数据包,从手机硬件、无线信号、光纤骨干,一路看到 TLS 握手和 GFW 的拟态博弈。 +> 顺着一个数据包,从手机硬件、无线信号、光纤骨干,一路看到 TLS 握手和 GFW 的拟态博弈。 ## 场景设定 -你站在上海某个咖啡馆门口,掏出手机(假设是一台开了 5G 的 iPhone),解锁,打开 Chrome,在 Google 搜索框里输入 `weather`,然后点击搜索按钮。 +你站在上海某个咖啡馆门口,掏出手机(假设是一台开了 5G 的 iPhone),解锁,打开 Chrome,在 Google 搜索框里输入 `weather`,然后点击搜索按钮。 -不到一秒钟,屏幕上就出现了天气预报。 +不到一秒钟,屏幕上就出现了天气预报。 -这"不到一秒钟"里发生的事情,可能比你想象的多得多。手机里的几十亿个晶体管做了无数次开关,无线电波在空中飞了一段,光脉冲在玻璃纤维里走了几千公里,十几台路由器和交换机查了表、改了头部、转了发,服务器机房里的网卡、CPU、内存接力处理。中间还涉及好几个数学难题——如果不是它们足够"难",你的搜索内容早就被人偷看了。 +这"不到一秒钟"里发生的事情,可能比你想象的多得多。手机里的几十亿个晶体管做了无数次开关,无线电波在空中飞了一段,光脉冲在玻璃纤维里走了几千公里,十几台路由器和交换机查了表、改了头部、转了发,服务器机房里的网卡、CPU、内存接力处理。中间还涉及好几个数学难题——如果不是它们足够"难",你的搜索内容早就被人偷看了。 -这篇文档会顺着这个数据包,从你的指尖一路走到 Google 的服务器,再走回来。 +这篇文档会顺着这个数据包,从你的指尖一路走到 Google 的服务器,再走回来。 ### 为什么值得花两个小时读完 -互联网能稳定运转,不是某个绝顶聪明的人造出来的,而是几代人、来自完全不同领域、彼此往往互不相识,把各自学科里最硬的一块刚好拼在了一起。 +互联网能稳定运转,不是某个绝顶聪明的人造出来的,而是几代人、来自完全不同领域、彼此往往互不相识,把各自学科里最硬的一块刚好拼在了一起。 -- 物理学家说"光在玻璃里靠全反射不漏",于是有了光纤 -- 数学家说"模幂运算正算容易、反算极难",于是有了 HTTPS +- 物理学家说"光在玻璃里靠全反射不漏",于是有了光纤 +- 数学家说"模幂运算正算容易、反算极难",于是有了 HTTPS -读完这篇,**你不会变成网络工程师**,但你会得到一种横向看穿整条链路的视角:从手机硬件、无线信号、光纤骨干,到 TLS 握手、GFW 的旁路镜像、Reality 的 TLS 拟态——它们是同一条故事线上的不同章节。 +读完这篇,**你不会变成网络工程师**,但你会得到一种横向看穿整条链路的视角:从手机硬件、无线信号、光纤骨干,到 TLS 握手、GFW 的旁路镜像、Reality 的 TLS 拟态——它们是同一条故事线上的不同章节。 -每一次你打开手机搜东西,这整套机制都为你跑了一遍。 +每一次你打开手机搜东西,这整套机制都为你跑了一遍。 ### 怎么读这篇 -文档很长(约 1100 行),不需要一口气读完: +文档很长(约 1100 行),不需要一口气读完: -- **不熟技术**:重点看[第 0 章](#第-0-章-全景)(全景)、[每章末尾的"这一章的物理 / 数学"小结]、[附录 C](#附录-c-底层物理与数学原理速览)(原理速览),其余按兴趣挑章读 -- **想看密码学怎么工作**:直奔[第 9 章](#第-9-章-tls-握手让中间人看不懂)(TLS 握手) -- **想理解翻墙原理**:直奔[第 6 章](#第-6-章-gfw-与翻墙一场-https-拟态的猫鼠游戏)(GFW 与 Reality) -- **只想看哲思**:看[场景设定](#场景设定)、[附录 D](#附录-d-那些刚刚好的巧合)("刚刚好"的巧合)、[写在最后](#写在最后) -- **要查公式**:[附录 A](#附录-a-关键公式速查)是分类速查表 +- **不熟技术**:重点看[第 0 章](#第-0-章-全景)(全景)、[每章末尾的"这一章的物理 / 数学"小结]、[附录 C](#附录-c-底层物理与数学原理速览)(原理速览),其余按兴趣挑章读 +- **想看密码学怎么工作**:直奔[第 9 章](#第-9-章-tls-握手让中间人看不懂)(TLS 握手) +- **想理解翻墙原理**:直奔[第 6 章](#第-6-章-gfw-与翻墙一场-https-拟态的猫鼠游戏)(GFW 与 Reality) +- **只想看哲思**:看[场景设定](#场景设定)、[附录 D](#附录-d-那些刚刚好的巧合)("刚刚好"的巧合)、[写在最后](#写在最后) +- **要查公式**:[附录 A](#附录-a-关键公式速查)是分类速查表 -公式不必逐条算明白。整篇文档的目标不是教你"怎么算",是让你看见"哪条物理 / 数学定律,在这条链路的哪一步,默默地起着什么作用"。 +公式不必逐条算明白。整篇文档的目标不是教你"怎么算",是让你看见"哪条物理 / 数学定律,在这条链路的哪一步,默默地起着什么作用"。 --- ## 目录 - [第 0 章 全景](#第-0-章-全景) -- [第 1 章 起点:手机内部](#第-1-章-起点手机内部) -- [第 2 章 第一次握手:DNS 查询](#第-2-章-第一次握手dns-查询) -- [第 3 章 接入层:5G 把数据送上天](#第-3-章-接入层5g-把数据送上天) -- [第 4 章 接入网:基站到核心网](#第-4-章-接入网基站到核心网) -- [第 5 章 城域网与骨干网:光纤里的高速公路](#第-5-章-城域网与骨干网光纤里的高速公路) -- [第 6 章 GFW 与翻墙:一场 HTTPS 拟态的猫鼠游戏](#第-6-章-gfw-与翻墙一场-https-拟态的猫鼠游戏) -- [第 7 章 跨洋:海底电缆](#第-7-章-跨洋海底电缆) -- [第 8 章 TCP 三次握手:在虚拟世界里建立连接](#第-8-章-tcp-三次握手在虚拟世界里建立连接) -- [第 9 章 TLS 握手:让中间人看不懂](#第-9-章-tls-握手让中间人看不懂) +- [第 1 章 起点:手机内部](#第-1-章-起点手机内部) +- [第 2 章 第一次握手:DNS 查询](#第-2-章-第一次握手dns-查询) +- [第 3 章 接入层:5G 把数据送上天](#第-3-章-接入层5g-把数据送上天) +- [第 4 章 接入网:基站到核心网](#第-4-章-接入网基站到核心网) +- [第 5 章 城域网与骨干网:光纤里的高速公路](#第-5-章-城域网与骨干网光纤里的高速公路) +- [第 6 章 GFW 与翻墙:一场 HTTPS 拟态的猫鼠游戏](#第-6-章-gfw-与翻墙一场-https-拟态的猫鼠游戏) +- [第 7 章 跨洋:海底电缆](#第-7-章-跨洋海底电缆) +- [第 8 章 TCP 三次握手:在虚拟世界里建立连接](#第-8-章-tcp-三次握手在虚拟世界里建立连接) +- [第 9 章 TLS 握手:让中间人看不懂](#第-9-章-tls-握手让中间人看不懂) - [第 10 章 数据中心入口](#第-10-章-数据中心入口) - [第 11 章 服务器内部](#第-11-章-服务器内部) - [第 12 章 丢包、误码与补救](#第-12-章-丢包误码与补救) - [第 13 章 硬件加速汇总](#第-13-章-硬件加速汇总) -- [第 14 章 返回:数据包的回家路](#第-14-章-返回数据包的回家路) +- [第 14 章 返回:数据包的回家路](#第-14-章-返回数据包的回家路) - [附录 A 关键公式速查](#附录-a-关键公式速查) - [附录 B 涉及的硬件芯片举例](#附录-b-涉及的硬件芯片举例) - [附录 C 底层物理与数学原理速览](#附录-c-底层物理与数学原理速览) @@ -73,7 +73,7 @@ draft: false ## 第 0 章 全景 -在我们钻进任何一层细节之前,先看一眼这个数据包要走完的路径: +在我们钻进任何一层细节之前,先看一眼这个数据包要走完的路径: ``` 你的手指 → 触摸屏 → CPU → 内存 → 基带芯片 → 射频前端 → 天线 @@ -82,153 +82,153 @@ draft: false → 边缘路由器 → 负载均衡器 → 接入服务器 → 应用服务器 ``` -物理上,这一路涉及:几十亿个晶体管、几十根毫米级天线、几公里到几千公里的光纤、几十个集成电路芯片、几台机柜大小的设备、可能还有一段几千公里长的海底电缆。 +物理上,这一路涉及:几十亿个晶体管、几十根毫米级天线、几公里到几千公里的光纤、几十个集成电路芯片、几台机柜大小的设备、可能还有一段几千公里长的海底电缆。 -软件上,涉及:URL 解析、DNS 协议、TCP/IP 协议栈、TLS 加密、HTTP 协议、HTML 渲染。 +软件上,涉及:URL 解析、DNS 协议、TCP/IP 协议栈、TLS 加密、HTTP 协议、HTML 渲染。 -数学上,涉及:傅里叶变换、椭圆曲线密码学、Reed-Solomon 编码、LDPC 码、Diffie-Hellman 密钥交换、AES 分组密码、矩阵运算(MIMO)、信息论(香农极限)。 +数学上,涉及:傅里叶变换、椭圆曲线密码学、Reed-Solomon 编码、LDPC 码、Diffie-Hellman 密钥交换、AES 分组密码、矩阵运算(MIMO)、信息论(香农极限)。 -物理上更深一层,这些技术全都建立在几条最底层的定律上:**Maxwell 方程组**(电磁波怎么传播)、**量子力学**(晶体管为什么能开关、激光为什么能发出)、**热力学第二定律**(噪声为什么消不掉)、**全反射**(光为什么不会从光纤侧面漏出去)、**受激辐射**(EDFA 怎么把光放大)。 +物理上更深一层,这些技术全都建立在几条最底层的定律上:**Maxwell 方程组**(电磁波怎么传播)、**量子力学**(晶体管为什么能开关、激光为什么能发出)、**热力学第二定律**(噪声为什么消不掉)、**全反射**(光为什么不会从光纤侧面漏出去)、**受激辐射**(EDFA 怎么把光放大)。 -数学上还有几个不那么显眼但更基础的支柱:**数论**(质数、模幂、欧拉定理——所有公钥密码的根基)、**群论 / 有限域**(椭圆曲线、AES 的 GF(2⁸) 列混合)、**计算复杂性理论**(为什么"加密容易、破解难")、**信息论**(香农定理告诉我们一个信道最多能传多少)、**线性代数**(MIMO 的信道矩阵 / 波束赋形)、**排队论**(路由器缓冲、TCP 拥塞控制)。 +数学上还有几个不那么显眼但更基础的支柱:**数论**(质数、模幂、欧拉定理——所有公钥密码的根基)、**群论 / 有限域**(椭圆曲线、AES 的 GF(2⁸) 列混合)、**计算复杂性理论**(为什么"加密容易、破解难")、**信息论**(香农定理告诉我们一个信道最多能传多少)、**线性代数**(MIMO 的信道矩阵 / 波束赋形)、**排队论**(路由器缓冲、TCP 拥塞控制)。 -完整的底层原理速览见 [附录 C](#附录-c-底层物理与数学原理速览),不想被卡在公式里的话直接跳过去看那张分类表也行。下面我们一层一层往下看,每章末尾会用一小节点出"这一步背后是哪条定律 / 哪种数学"。 +完整的底层原理速览见 [附录 C](#附录-c-底层物理与数学原理速览),不想被卡在公式里的话直接跳过去看那张分类表也行。下面我们一层一层往下看,每章末尾会用一小节点出"这一步背后是哪条定律 / 哪种数学"。 ### 0.1 顺手把 HTTPS 拆成它的零件 -整篇文档的标题里写着 **HTTPS**,但 HTTPS **不是一个独立的协议**,而是好几个协议**叠在一起**的总称。先把这一点讲清楚,后面所有章节的位置感才对得上。 +整篇文档的标题里写着 **HTTPS**,但 HTTPS **不是一个独立的协议**,而是好几个协议**叠在一起**的总称。先把这一点讲清楚,后面所有章节的位置感才对得上。 | 层 | 协议 | 干什么 | 在哪一章细讲 | |----|------|--------|------------| -| 应用层 | **HTTP** | 发的是什么内容(GET / POST、URL、headers、body) | §1.2 浏览器准备 HTTP 请求 | -| 安全层 | **TLS** | 给应用层加密 + 验证身份(HTTPS 里那个**"S"**) | 第 9 章 | -| 传输层 | **TCP** | 把字节流可靠送达(三次握手、重传、拥塞控制) | 第 8 章、第 12 章 | -| 网络层 | **IP** + 路由 | 寻址,让包能跨网络走 | 第 5 章 | +| 应用层 | **HTTP** | 发的是什么内容(GET / POST、URL、headers、body) | §1.2 浏览器准备 HTTP 请求 | +| 安全层 | **TLS** | 给应用层加密 + 验证身份(HTTPS 里那个**"S"**) | 第 9 章 | +| 传输层 | **TCP** | 把字节流可靠送达(三次握手、重传、拥塞控制) | 第 8 章、第 12 章 | +| 网络层 | **IP** + 路由 | 寻址,让包能跨网络走 | 第 5 章 | | 物理层 | 5G / 光纤 / 铜缆 | 真把电磁波 / 光子送到对面去 | 第 1-3 章、第 7 章 | -一句话总结:**HTTPS = HTTP 跑在 TLS 里,TLS 跑在 TCP 里,TCP 跑在 IP 里,IP 跑在物理介质里**。 +一句话总结:**HTTPS = HTTP 跑在 TLS 里,TLS 跑在 TCP 里,TCP 跑在 IP 里,IP 跑在物理介质里**。 -具体到你输入 `https://www.google.com` 这一刻,实际发生的是: +具体到你输入 `https://www.google.com` 这一刻,实际发生的是: -1. **建管道**:你和 Google 之间用 TCP 三次握手建一条字节流通道(第 8 章) -2. **加密管道**:在这条 TCP 通道里用 TLS 握手再套一层加密 + 身份验证的"暗管"(第 9 章) -3. **送内容**:你的 HTTP 请求(`GET /search?q=weather HTTP/1.1\r\nHost: www.google.com\r\n...`)的字节流,从这条暗管里钻过去——中间路过的人能看到流量、看不到内容 -4. **拆暗管**:Google 服务器在另一端把暗管解开,看到 HTTP 请求,处理后把响应原路塞回去 +1. **建管道**:你和 Google 之间用 TCP 三次握手建一条字节流通道(第 8 章) +2. **加密管道**:在这条 TCP 通道里用 TLS 握手再套一层加密 + 身份验证的"暗管"(第 9 章) +3. **送内容**:你的 HTTP 请求(`GET /search?q=weather HTTP/1.1\r\nHost: www.google.com\r\n...`)的字节流,从这条暗管里钻过去——中间路过的人能看到流量、看不到内容 +4. **拆暗管**:Google 服务器在另一端把暗管解开,看到 HTTP 请求,处理后把响应原路塞回去 -剥掉 TLS,就是 80 端口的明文 **HTTP**,中间任何路由器、运营商、咖啡店 Wi-Fi 都能看;加上 TLS,就是 443 端口的 **HTTPS**,内容只有你和 Google 看得到。**这一字之差,养活了密码学这一整门学科,也撑起了整个第 9 章和第 6 章 GFW 与 Reality 的猫鼠游戏**——后者本质上就是一场"如何让 HTTPS 看起来更像普通 HTTPS"的工程对抗。 +剥掉 TLS,就是 80 端口的明文 **HTTP**,中间任何路由器、运营商、咖啡店 Wi-Fi 都能看;加上 TLS,就是 443 端口的 **HTTPS**,内容只有你和 Google 看得到。**这一字之差,养活了密码学这一整门学科,也撑起了整个第 9 章和第 6 章 GFW 与 Reality 的猫鼠游戏**——后者本质上就是一场"如何让 HTTPS 看起来更像普通 HTTPS"的工程对抗。 -记住这张五层栈,下面的每一章你都能定位到自己在哪一层:**第 1-3、7 章在物理层底下做事,第 5 章是网络层 IP 怎么找路,第 8 章管 TCP 建管道,第 9 章管 TLS 加密,第 6 章管"管道在国境线被卡时怎么办"**。 +记住这张五层栈,下面的每一章你都能定位到自己在哪一层:**第 1-3、7 章在物理层底下做事,第 5 章是网络层 IP 怎么找路,第 8 章管 TCP 建管道,第 9 章管 TLS 加密,第 6 章管"管道在国境线被卡时怎么办"**。 --- -## 第 1 章 起点:手机内部 +## 第 1 章 起点:手机内部 ### 1.1 触摸屏识别到了你的点击 -你的手指按在屏幕"搜索"按钮的位置。屏幕表面是一层电容式触控层,由透明的氧化铟锡(ITO)电极组成网格。你的手指带着微弱的电荷,改变了某个交叉点的电容值。触控芯片(在 iPhone 里是苹果自研的多点触控控制器)以 120Hz 扫描整个网格,检测到了变化,把"在 (x, y) 处发生了一次触摸"这条事件通过 SPI 或 I2C 总线发给主 SoC(A 系列芯片)。 +你的手指按在屏幕"搜索"按钮的位置。屏幕表面是一层电容式触控层,由透明的氧化铟锡(ITO)电极组成网格。你的手指带着微弱的电荷,改变了某个交叉点的电容值。触控芯片(在 iPhone 里是苹果自研的多点触控控制器)以 120Hz 扫描整个网格,检测到了变化,把"在 (x, y) 处发生了一次触摸"这条事件通过 SPI 或 I2C 总线发给主 SoC(A 系列芯片)。 -**底层原理**:平板电容公式 `C = ε × A / d`(电容 = 介电常数 × 极板面积 / 极板间距)。你的手指本身是个含水量很高的导体,贴近屏幕时相当于在原本的电极对上叠加了一个新的"对地电容",于是 `C` 突然变大。触控芯片本质上是用一个 RC 振荡电路或电荷转移电路在每个交叉点测电容,任何一个点的电容偏离基线就报点。所以"湿手"或者"戴手套"会失灵——前者改变了介电常数,后者切断了导电通路。 +**底层原理**:平板电容公式 `C = ε × A / d`(电容 = 介电常数 × 极板面积 / 极板间距)。你的手指本身是个含水量很高的导体,贴近屏幕时相当于在原本的电极对上叠加了一个新的"对地电容",于是 `C` 突然变大。触控芯片本质上是用一个 RC 振荡电路或电荷转移电路在每个交叉点测电容,任何一个点的电容偏离基线就报点。所以"湿手"或者"戴手套"会失灵——前者改变了介电常数,后者切断了导电通路。 -主 SoC 的 CPU(目前是 ARMv9 架构)收到中断,iOS 的内核唤醒 Chrome 进程,把事件传给浏览器的 UI 线程。浏览器的事件处理代码识别出这是一次"点击搜索"操作。 +主 SoC 的 CPU(目前是 ARMv9 架构)收到中断,iOS 的内核唤醒 Chrome 进程,把事件传给浏览器的 UI 线程。浏览器的事件处理代码识别出这是一次"点击搜索"操作。 -**晶体管在干什么**:这个 SoC 里有大约 200 亿个晶体管,基本结构是 MOSFET(金属氧化物半导体场效应管)。它的开关原理是:在栅极加正电压,栅极下的硅衬底会形成一层"反型层",导通源极和漏极;撤掉电压,通道消失,断开。这是量子力学允许的现象——电子在能带结构里被电场推到导带。**先进工艺(3nm)下,栅极厚度只有几个原子层**,电子有一定概率"穿过"绝缘层而不是被挡住,这叫**量子隧穿**,也是为什么再往下做工艺会有漏电墙——物理定律开始反对你了。 +**晶体管在干什么**:这个 SoC 里有大约 200 亿个晶体管,基本结构是 MOSFET(金属氧化物半导体场效应管)。它的开关原理是:在栅极加正电压,栅极下的硅衬底会形成一层"反型层",导通源极和漏极;撤掉电压,通道消失,断开。这是量子力学允许的现象——电子在能带结构里被电场推到导带。**先进工艺(3nm)下,栅极厚度只有几个原子层**,电子有一定概率"穿过"绝缘层而不是被挡住,这叫**量子隧穿**,也是为什么再往下做工艺会有漏电墙——物理定律开始反对你了。 ### 1.2 浏览器准备 HTTP 请求 -Chrome 内部知道你要去 `https://www.google.com/search?q=weather`。它先做几件事,全在 CPU 和内存里完成,没有任何网络流量: +Chrome 内部知道你要去 `https://www.google.com/search?q=weather`。它先做几件事,全在 CPU 和内存里完成,没有任何网络流量: -**URL 解析**:按 RFC 3986 把 URL 拆成五部分——`scheme=https`、`host=www.google.com`、`port=443`(默认)、`path=/search`、`query=q=weather`。 +**URL 解析**:按 RFC 3986 把 URL 拆成五部分——`scheme=https`、`host=www.google.com`、`port=443`(默认)、`path=/search`、`query=q=weather`。 -**HSTS 检查**:浏览器内置一份"必须用 HTTPS"的网站列表(HSTS preload list),Google 在里面。即使你输入的是 `http://`,也会被强制升级到 `https://`。 +**HSTS 检查**:浏览器内置一份"必须用 HTTPS"的网站列表(HSTS preload list),Google 在里面。即使你输入的是 `http://`,也会被强制升级到 `https://`。 -**缓存查找**:浏览器先看自己有没有这个域名的 DNS 记录、有没有可复用的 TCP 连接、有没有可复用的 TLS 会话。如果有,就能跳过后面好几个阶段。 +**缓存查找**:浏览器先看自己有没有这个域名的 DNS 记录、有没有可复用的 TCP 连接、有没有可复用的 TLS 会话。如果有,就能跳过后面好几个阶段。 -我们假设全部没命中,需要从头走一遍。 +我们假设全部没命中,需要从头走一遍。 ### 1.3 数据从 CPU 流向基带芯片 -Chrome 调用 iOS 的 `Network.framework`,最终落到 BSD socket 接口。内核构造 TCP/IP 数据包,但还不能直接发——还得先解析域名。 +Chrome 调用 iOS 的 `Network.framework`,最终落到 BSD socket 接口。内核构造 TCP/IP 数据包,但还不能直接发——还得先解析域名。 -域名解析的请求(一个 DNS 查询包)被内核交给"网络硬件抽象层",最终经过内部总线送到基带芯片(modem)。 +域名解析的请求(一个 DNS 查询包)被内核交给"网络硬件抽象层",最终经过内部总线送到基带芯片(modem)。 -iPhone 的基带芯片目前是高通 X 系列(比如 X75 调制解调器),它是一块独立的大芯片,通过 PCIe 总线和主 SoC 通讯。基带芯片专门负责"和无线世界打交道",它内部有自己的 ARM 处理器、DSP(数字信号处理器)、专用的物理层加速电路。 +iPhone 的基带芯片目前是高通 X 系列(比如 X75 调制解调器),它是一块独立的大芯片,通过 PCIe 总线和主 SoC 通讯。基带芯片专门负责"和无线世界打交道",它内部有自己的 ARM 处理器、DSP(数字信号处理器)、专用的物理层加速电路。 -主 SoC 把要发的数据通过 DMA(直接内存访问)的方式写到基带芯片能读的内存区域,然后给基带一个中断信号说"有新数据了"。 +主 SoC 把要发的数据通过 DMA(直接内存访问)的方式写到基带芯片能读的内存区域,然后给基带一个中断信号说"有新数据了"。 -**这里多拆一层:数据是怎么"在芯片间走"的**。SoC 和基带之间是 PCIe 总线,本质上是几对差分信号线(每对两根,一正一负,值靠两根之间的电压差判读,抗干扰),每秒切换几十亿次,每次切换就是一个比特。芯片内部 0 和 1 是 CMOS 电路里两个电压电平(典型 0V 和 0.8V),靠 PMOS / NMOS 互补开关把电平翻过去——这又回到 MOSFET 的事。 +**这里多拆一层:数据是怎么"在芯片间走"的**。SoC 和基带之间是 PCIe 总线,本质上是几对差分信号线(每对两根,一正一负,值靠两根之间的电压差判读,抗干扰),每秒切换几十亿次,每次切换就是一个比特。芯片内部 0 和 1 是 CMOS 电路里两个电压电平(典型 0V 和 0.8V),靠 PMOS / NMOS 互补开关把电平翻过去——这又回到 MOSFET 的事。 -到这里,数据还是数字形式,以 0 和 1 的电信号在芯片间传递。下一步,要变成无线电波了。 +到这里,数据还是数字形式,以 0 和 1 的电信号在芯片间传递。下一步,要变成无线电波了。 -**这一章的物理 / 数学**:电容物理(`C = εA/d`)→ 触摸识别;半导体能带理论 + MOSFET 反型层 → 晶体管开关;量子隧穿 → 工艺微缩的物理边界;CMOS 互补对称 → 数字电路的电平表示。 +**这一章的物理 / 数学**:电容物理(`C = εA/d`)→ 触摸识别;半导体能带理论 + MOSFET 反型层 → 晶体管开关;量子隧穿 → 工艺微缩的物理边界;CMOS 互补对称 → 数字电路的电平表示。 --- -## 第 2 章 第一次握手:DNS 查询 +## 第 2 章 第一次握手:DNS 查询 ### 2.1 为什么要查 DNS -互联网上的服务器是用 IP 地址定位的,比如 `142.250.71.46`。但人记不住这种数字,所以发明了域名,需要一个"翻译系统"把域名翻译成 IP——这就是 DNS(Domain Name System)。 +互联网上的服务器是用 IP 地址定位的,比如 `142.250.71.46`。但人记不住这种数字,所以发明了域名,需要一个"翻译系统"把域名翻译成 IP——这就是 DNS(Domain Name System)。 ### 2.2 查询过程 -你的手机里装着运营商分配的 DNS 服务器地址(在 5G 时代经常是 `223.5.5.5` 阿里 DNS 或 `114.114.114.114`)。手机把"www.google.com 的 IP 是多少?"这个问题发给这台 DNS 服务器,这台服务器叫"递归解析器"。 +你的手机里装着运营商分配的 DNS 服务器地址(在 5G 时代经常是 `223.5.5.5` 阿里 DNS 或 `114.114.114.114`)。手机把"www.google.com 的 IP 是多少?"这个问题发给这台 DNS 服务器,这台服务器叫"递归解析器"。 -如果递归解析器自己缓存里没有答案,它会代你去问: +如果递归解析器自己缓存里没有答案,它会代你去问: -1. 先问根服务器(全球 13 组,实际有几百台,用 anycast 技术让你访问最近的一台):"www.google.com 谁管?"根服务器答:"我不知道,但 .com 顶级域归这堆服务器管,你去问它们。" -2. 再问 .com 顶级域服务器:"www.google.com 谁管?".com 答:"google.com 这个域是这堆权威服务器管,问它们去。" -3. 最后问 google.com 的权威服务器(由 Google 自己运营):"www.google.com 的 IP 是多少?"权威服务器答:"142.250.71.46"。 +1. 先问根服务器(全球 13 组,实际有几百台,用 anycast 技术让你访问最近的一台):"www.google.com 谁管?"根服务器答:"我不知道,但 .com 顶级域归这堆服务器管,你去问它们。" +2. 再问 .com 顶级域服务器:"www.google.com 谁管?".com 答:"google.com 这个域是这堆权威服务器管,问它们去。" +3. 最后问 google.com 的权威服务器(由 Google 自己运营):"www.google.com 的 IP 是多少?"权威服务器答:"142.250.71.46"。 -整个过程,递归解析器记下答案缓存若干分钟,然后把结果返回给你的手机。 +整个过程,递归解析器记下答案缓存若干分钟,然后把结果返回给你的手机。 ### 2.3 DNS 包长什么样 -DNS 是一个非常紧凑的二进制协议,默认走 UDP 53 端口。一个标准查询大约 60-80 字节: +DNS 是一个非常紧凑的二进制协议,默认走 UDP 53 端口。一个标准查询大约 60-80 字节: -- **12 字节头部**:16 位事务 ID(用于匹配请求和响应)、标志位(查询/响应、递归/迭代等)、问题数、答案数等。 -- **问题段**:把域名编码成"长度+内容"的形式。`www.google.com` 编码为 `\x03www\x06google\x03com\x00`。 -- **类型和类**:2 字节类型(A 记录=1,代表 IPv4 地址)、2 字节类(IN=1,互联网)。 +- **12 字节头部**:16 位事务 ID(用于匹配请求和响应)、标志位(查询/响应、递归/迭代等)、问题数、答案数等。 +- **问题段**:把域名编码成"长度+内容"的形式。`www.google.com` 编码为 `\x03www\x06google\x03com\x00`。 +- **类型和类**:2 字节类型(A 记录=1,代表 IPv4 地址)、2 字节类(IN=1,互联网)。 -UDP 头再加 8 字节、IP 头再加 20 字节、以太网/无线帧头再加几十字节,这个 DNS 查询就准备好出发了。 +UDP 头再加 8 字节、IP 头再加 20 字节、以太网/无线帧头再加几十字节,这个 DNS 查询就准备好出发了。 ### 2.4 现代加密 DNS -传统 DNS 是明文的,运营商和中间任何人都能看见、能篡改。所以现在有了加密 DNS: +传统 DNS 是明文的,运营商和中间任何人都能看见、能篡改。所以现在有了加密 DNS: -- **DoT(DNS over TLS)**:走 853 端口,在 TLS 加密通道里发 DNS 查询。 -- **DoH(DNS over HTTPS)**:走 443 端口,把 DNS 查询封装在 HTTPS 请求里。Google、Cloudflare 都提供。 +- **DoT(DNS over TLS)**:走 853 端口,在 TLS 加密通道里发 DNS 查询。 +- **DoH(DNS over HTTPS)**:走 443 端口,把 DNS 查询封装在 HTTPS 请求里。Google、Cloudflare 都提供。 -iPhone iOS 14 之后默认支持 DoH。我们假设你的手机用了 DoH,那么 DNS 查询本身就要先做一次完整的 TLS 握手——不过这不重要,我们就当它已经查到了 `www.google.com → 142.250.71.46`。 +iPhone iOS 14 之后默认支持 DoH。我们假设你的手机用了 DoH,那么 DNS 查询本身就要先做一次完整的 TLS 握手——不过这不重要,我们就当它已经查到了 `www.google.com → 142.250.71.46`。 --- -## 第 3 章 接入层:5G 把数据送上天 +## 第 3 章 接入层:5G 把数据送上天 现在重点来了。手机要把"打开 142.250.71.46 的 443 端口"这件事告诉基站。 ### 3.0 先把"无线电波"是什么搞清楚 -无线电波、可见光、X 射线、伽马射线,都是一种东西——**电磁波**,只是频率不同。它们的存在与传播,被一组方程组完全描述,这就是 1865 年 **詹姆斯·克拉克·麦克斯韦(James Clerk Maxwell)** 写下的 **Maxwell 方程组**:四条偏微分方程,告诉你电场和磁场怎么互相激发、怎么在真空里以光速 `c ≈ 3 × 10⁸ m/s` 向四周扩散。整个无线通信、光纤通信、雷达、GPS、Wi-Fi、5G,都建立在这四条方程上,Maxwell 当年并不知道这些会被发明出来——直到 1887 年 **赫兹(Heinrich Hertz)** 才在实验室里第一次造出了无线电波。 +无线电波、可见光、X 射线、伽马射线,都是一种东西——**电磁波**,只是频率不同。它们的存在与传播,被一组方程组完全描述,这就是 1865 年 **詹姆斯·克拉克·麦克斯韦(James Clerk Maxwell)** 写下的 **Maxwell 方程组**:四条偏微分方程,告诉你电场和磁场怎么互相激发、怎么在真空里以光速 `c ≈ 3 × 10⁸ m/s` 向四周扩散。整个无线通信、光纤通信、雷达、GPS、Wi-Fi、5G,都建立在这四条方程上,Maxwell 当年并不知道这些会被发明出来——直到 1887 年 **赫兹(Heinrich Hertz)** 才在实验室里第一次造出了无线电波。 -频率(`f`,Hz)和波长(`λ`,m)的关系简单到只有一个公式: +频率(`f`,Hz)和波长(`λ`,m)的关系简单到只有一个公式: ``` c = λ × f ``` -代进去:5G n78 频段载波 3.5 GHz,对应波长大约 8.6 厘米。毫米波 28 GHz 对应波长 1 厘米。Wi-Fi 5GHz 对应 6 厘米。可见光 500 THz 对应 600 nm。手机里的天线长度是波长的 1/4 或 1/2 量级——这就是为什么 5G 频段越高,手机里的天线就越小,基站的天线阵列也越能塞进更多根。 +代进去:5G n78 频段载波 3.5 GHz,对应波长大约 8.6 厘米。毫米波 28 GHz 对应波长 1 厘米。Wi-Fi 5GHz 对应 6 厘米。可见光 500 THz 对应 600 nm。手机里的天线长度是波长的 1/4 或 1/2 量级——这就是为什么 5G 频段越高,手机里的天线就越小,基站的天线阵列也越能塞进更多根。 -电磁波从天线发出去后能量按 1/r² 扩散(球面),所以越远信号越弱。**Friis 路径损耗公式**给出"理想条件下接收功率": +电磁波从天线发出去后能量按 1/r² 扩散(球面),所以越远信号越弱。**Friis 路径损耗公式**给出"理想条件下接收功率": ``` P_r = P_t × G_t × G_r × (λ / 4πr)² ``` -`P_t / P_r` 是发射 / 接收功率,`G_t / G_r` 是天线增益,`r` 是距离。可以记住一条直觉:**距离翻倍,功率衰减 4 倍(6 dB)**。这条公式给运营商规划基站密度。 +`P_t / P_r` 是发射 / 接收功率,`G_t / G_r` 是天线增益,`r` 是距离。可以记住一条直觉:**距离翻倍,功率衰减 4 倍(6 dB)**。这条公式给运营商规划基站密度。 ### 3.1 基带芯片在干什么 -基带芯片(modem)拿到要发的数据后,要做一系列复杂的处理才能交给天线发出去。这套处理流程叫"物理层处理"(PHY processing),大致顺序是: +基带芯片(modem)拿到要发的数据后,要做一系列复杂的处理才能交给天线发出去。这套处理流程叫"物理层处理"(PHY processing),大致顺序是: ``` 原始数据 @@ -245,128 +245,128 @@ P_r = P_t × G_t × G_r × (λ / 4πr)² 每一步都有专门的硬件电路或 DSP 加速。下面挑几个最关键的展开。 -### 3.2 信道编码:5G 用的是 LDPC 和 Polar +### 3.2 信道编码:5G 用的是 LDPC 和 Polar -无线信道是出了名的不可靠——会衰减、会反射、会被其他信号干扰、会被一辆开过去的卡车挡住。要在这种信道上可靠地传数据,必须加冗余。这就是"信道编码"或叫"前向纠错"(FEC,Forward Error Correction)。 +无线信道是出了名的不可靠——会衰减、会反射、会被其他信号干扰、会被一辆开过去的卡车挡住。要在这种信道上可靠地传数据,必须加冗余。这就是"信道编码"或叫"前向纠错"(FEC,Forward Error Correction)。 -**LDPC 码**(低密度奇偶校验码)用于 5G 的数据信道。原理是给原始数据加上一堆奇偶校验位,这些校验位之间的关系可以用一个稀疏矩阵 H 描述。接收端如果发现某些位变了,可以通过迭代算法(比如置信传播算法)推算出原始数据。LDPC 码的性能可以非常接近"香农极限"。 +**LDPC 码**(低密度奇偶校验码)用于 5G 的数据信道。原理是给原始数据加上一堆奇偶校验位,这些校验位之间的关系可以用一个稀疏矩阵 H 描述。接收端如果发现某些位变了,可以通过迭代算法(比如置信传播算法)推算出原始数据。LDPC 码的性能可以非常接近"香农极限"。 -**Polar 码**(极化码)是华为主导推动进入 5G 标准的,用于控制信道。原理是利用"信道极化"现象,把多个并行信道转换成"几乎完全可靠"和"几乎完全不可靠"两类,然后只在可靠的那些信道上传数据。 +**Polar 码**(极化码)是华为主导推动进入 5G 标准的,用于控制信道。原理是利用"信道极化"现象,把多个并行信道转换成"几乎完全可靠"和"几乎完全不可靠"两类,然后只在可靠的那些信道上传数据。 -**香农极限**的公式是: +**香农极限**的公式是: ``` C = B × log₂(1 + SNR) ``` -其中 C 是信道容量(bps),B 是带宽(Hz),SNR 是信噪比。这个公式 1948 年由 **克劳德·香农(Claude Shannon)** 提出,被称为**香农定理(Shannon-Hartley Theorem)**,告诉我们一个信道理论上能传多少数据。LDPC 和 Polar 码就是为了尽可能逼近这个极限。 +其中 C 是信道容量(bps),B 是带宽(Hz),SNR 是信噪比。这个公式 1948 年由 **克劳德·香农(Claude Shannon)** 提出,被称为**香农定理(Shannon-Hartley Theorem)**,告诉我们一个信道理论上能传多少数据。LDPC 和 Polar 码就是为了尽可能逼近这个极限。 -### 3.3 调制:把比特变成复数 +### 3.3 调制:把比特变成复数 -调制就是把数字比特"塞"到电磁波里。最简单的方式是 **BPSK**(二相相移键控),用波形相位 0° 表示比特 0,180° 表示比特 1,每个符号传 1 比特。 +调制就是把数字比特"塞"到电磁波里。最简单的方式是 **BPSK**(二相相移键控),用波形相位 0° 表示比特 0,180° 表示比特 1,每个符号传 1 比特。 -5G 用的是 **QAM**(正交幅度调制),把幅度和相位结合起来。比如 64-QAM 把信号点摆在 8×8 的网格上,每个点对应 6 个比特;256-QAM 是 16×16 网格,每个点对应 8 个比特;5G 最高支持 1024-QAM,每个符号传 10 比特。 +5G 用的是 **QAM**(正交幅度调制),把幅度和相位结合起来。比如 64-QAM 把信号点摆在 8×8 的网格上,每个点对应 6 个比特;256-QAM 是 16×16 网格,每个点对应 8 个比特;5G 最高支持 1024-QAM,每个符号传 10 比特。 -调制阶数越高,传得越快,但对信噪比要求也越高——网格点越密,稍微一点噪声就会被识别成相邻的点,出错。所以基站会根据你的信号质量动态选用不同的调制方式:信号好就用 1024-QAM,信号差就降到 64-QAM 或 16-QAM。 +调制阶数越高,传得越快,但对信噪比要求也越高——网格点越密,稍微一点噪声就会被识别成相邻的点,出错。所以基站会根据你的信号质量动态选用不同的调制方式:信号好就用 1024-QAM,信号差就降到 64-QAM 或 16-QAM。 -### 3.4 OFDM:把数据撒在好几个频率上同时发 +### 3.4 OFDM:把数据撒在好几个频率上同时发 -**OFDM**(正交频分复用)是 4G/5G 的核心物理层技术。它的思路是:不要在一个频率上以非常高的速率发数据,而是把可用带宽分成几百几千个"子载波",每个子载波以较低的速率发,所有子载波同时发。 +**OFDM**(正交频分复用)是 4G/5G 的核心物理层技术。它的思路是:不要在一个频率上以非常高的速率发数据,而是把可用带宽分成几百几千个"子载波",每个子载波以较低的速率发,所有子载波同时发。 -这样有几个好处:每个子载波速率慢,符号周期长,不容易被多径反射干扰;可以根据每个子载波的信道质量动态分配功率和数据;频谱利用率高。 +这样有几个好处:每个子载波速率慢,符号周期长,不容易被多径反射干扰;可以根据每个子载波的信道质量动态分配功率和数据;频谱利用率高。 -OFDM 的核心数学工具是 **IFFT(快速傅里叶逆变换)**。基带芯片把要发的几千个子载波数据组成一个频域向量,做一次 IFFT,就得到要发的时域信号。这一步是计算密集型的,基带芯片里有专门的 FFT 硬件加速电路。再往上一层数学根是 **傅里叶变换**——任何信号都能拆成一堆不同频率正弦波的叠加,这条 1822 年由 **约瑟夫·傅里叶(Joseph Fourier)** 在研究热传导时提出的工具,后来撑起了几乎所有的数字信号处理。 +OFDM 的核心数学工具是 **IFFT(快速傅里叶逆变换)**。基带芯片把要发的几千个子载波数据组成一个频域向量,做一次 IFFT,就得到要发的时域信号。这一步是计算密集型的,基带芯片里有专门的 FFT 硬件加速电路。再往上一层数学根是 **傅里叶变换**——任何信号都能拆成一堆不同频率正弦波的叠加,这条 1822 年由 **约瑟夫·傅里叶(Joseph Fourier)** 在研究热传导时提出的工具,后来撑起了几乎所有的数字信号处理。 -公式上,OFDM 信号是: +公式上,OFDM 信号是: ``` s(t) = Σ Xₖ × exp(j2πkΔf·t) (k 从 0 到 N-1) ``` -其中 Xₖ 是第 k 个子载波上的复数符号,Δf 是子载波间隔(5G 中可以是 15kHz、30kHz、60kHz 等),N 是子载波总数。 +其中 Xₖ 是第 k 个子载波上的复数符号,Δf 是子载波间隔(5G 中可以是 15kHz、30kHz、60kHz 等),N 是子载波总数。 ### 3.5 射频前端和天线 -OFDM 信号还是数字的(IQ 两路实数信号)。基带芯片把它送到射频收发器(RF transceiver),DAC(数模转换器)把它变成模拟信号,混频器把它搬到目标载频(比如 5G n78 频段是 3.5GHz),然后送到射频前端。 +OFDM 信号还是数字的(IQ 两路实数信号)。基带芯片把它送到射频收发器(RF transceiver),DAC(数模转换器)把它变成模拟信号,混频器把它搬到目标载频(比如 5G n78 频段是 3.5GHz),然后送到射频前端。 -射频前端是手机里专门处理"高频小信号"的一组芯片,包括: +射频前端是手机里专门处理"高频小信号"的一组芯片,包括: -- **功率放大器(PA)**:把信号放大到几百毫瓦,才有能力发到几公里外的基站。手机的 PA 通常是砷化镓(GaAs)或氮化镓(GaN)工艺,因为硅在高频下效率不行。 -- **滤波器**:去掉杂散信号,只保留目标频段。手机里塞了几十个滤波器,因为要支持各种 4G/5G 频段。常见的是声表面波(SAW)和体声波(BAW)滤波器。 -- **天线开关**:在多根天线之间切换。 +- **功率放大器(PA)**:把信号放大到几百毫瓦,才有能力发到几公里外的基站。手机的 PA 通常是砷化镓(GaAs)或氮化镓(GaN)工艺,因为硅在高频下效率不行。 +- **滤波器**:去掉杂散信号,只保留目标频段。手机里塞了几十个滤波器,因为要支持各种 4G/5G 频段。常见的是声表面波(SAW)和体声波(BAW)滤波器。 +- **天线开关**:在多根天线之间切换。 -iPhone 的射频前端芯片以前主要来自 Skyworks 和 Qorvo,现在苹果在自研。 +iPhone 的射频前端芯片以前主要来自 Skyworks 和 Qorvo,现在苹果在自研。 -最后,信号驱动天线。iPhone 里有四根主要天线,分布在边框里(那些"白带子"就是塑料填充,让金属边框断开做天线)。5G 毫米波版本(主要是美版)还有专门的毫米波天线模组。 +最后,信号驱动天线。iPhone 里有四根主要天线,分布在边框里(那些"白带子"就是塑料填充,让金属边框断开做天线)。5G 毫米波版本(主要是美版)还有专门的毫米波天线模组。 -电磁波就这样从你的手机辐射出去了,以光速向四面八方传播。 +电磁波就这样从你的手机辐射出去了,以光速向四面八方传播。 -**这一章的物理 / 数学**:Maxwell 方程组(电磁波存在的基础)→ 一切无线通信;`c = λf`(频率 / 波长换算)→ 决定天线尺寸;Friis 公式(自由空间路径损耗)→ 基站规划密度;傅里叶变换 / IFFT(时频转换)→ OFDM 的核心;香农定理 `C = B log₂(1+SNR)`(信道容量上限)→ 编码 / 调制设计的目标;LDPC / Polar(信道编码)→ 在嘈杂信道里保住数据;QAM 星座图(几何上把比特排到复平面)→ 高阶调制。 +**这一章的物理 / 数学**:Maxwell 方程组(电磁波存在的基础)→ 一切无线通信;`c = λf`(频率 / 波长换算)→ 决定天线尺寸;Friis 公式(自由空间路径损耗)→ 基站规划密度;傅里叶变换 / IFFT(时频转换)→ OFDM 的核心;香农定理 `C = B log₂(1+SNR)`(信道容量上限)→ 编码 / 调制设计的目标;LDPC / Polar(信道编码)→ 在嘈杂信道里保住数据;QAM 星座图(几何上把比特排到复平面)→ 高阶调制。 --- -## 第 4 章 接入网:基站到核心网 +## 第 4 章 接入网:基站到核心网 ### 4.1 基站收到了你的信号 -你周围可能有好几个 5G 基站,你的手机会持续测量哪个信号最好,优先连那个。基站(在 5G 里叫 gNodeB,简称 gNB)是一组安装在铁塔或楼顶的设备,主要由两部分组成: +你周围可能有好几个 5G 基站,你的手机会持续测量哪个信号最好,优先连那个。基站(在 5G 里叫 gNodeB,简称 gNB)是一组安装在铁塔或楼顶的设备,主要由两部分组成: -- **AAU(有源天线单元)**:装在铁塔顶部,集成了天线阵列和射频电路。5G 基站用 64T64R(64 收 64 发)甚至更大规模的 **Massive MIMO** 天线阵列。 -- **BBU(基带处理单元)**:装在铁塔下面的机房或机柜里,是真正做数字信号处理的地方。 +- **AAU(有源天线单元)**:装在铁塔顶部,集成了天线阵列和射频电路。5G 基站用 64T64R(64 收 64 发)甚至更大规模的 **Massive MIMO** 天线阵列。 +- **BBU(基带处理单元)**:装在铁塔下面的机房或机柜里,是真正做数字信号处理的地方。 -AAU 和 BBU 之间用光纤连接,接口标准叫 **CPRI** 或 **eCPRI**。 +AAU 和 BBU 之间用光纤连接,接口标准叫 **CPRI** 或 **eCPRI**。 ### 4.2 Massive MIMO 和波束赋形 -5G 基站为什么要这么多根天线?因为要做"波束赋形"(beamforming)。 +5G 基站为什么要这么多根天线?因为要做"波束赋形"(beamforming)。 -普通天线是全向辐射,能量浪费在不需要的方向上。Massive MIMO 通过让 64 根天线发出相位略有差异的信号,让信号在空间中"叠加"出一个指向你手机方向的窄波束。其他方向上信号会因为相位抵消而变弱。 +普通天线是全向辐射,能量浪费在不需要的方向上。Massive MIMO 通过让 64 根天线发出相位略有差异的信号,让信号在空间中"叠加"出一个指向你手机方向的窄波束。其他方向上信号会因为相位抵消而变弱。 -**底层原理是波的干涉**:两列相位相同的波叠加,振幅加倍(相长干涉);相位相反,完全抵消(相消干涉)。这是 1801 年 **托马斯·杨(Thomas Young)** 用双缝实验展示的经典波动现象。Massive MIMO 把它放大到 64 维:每根天线的相位是一个旋钮,调好这 64 个旋钮,就能让所有波在你这个点相加,在别的点互相抵消。手机之所以收得到信号,是因为 64 个射出去的波恰好在你手机这一寸空间里"相长干涉"。 +**底层原理是波的干涉**:两列相位相同的波叠加,振幅加倍(相长干涉);相位相反,完全抵消(相消干涉)。这是 1801 年 **托马斯·杨(Thomas Young)** 用双缝实验展示的经典波动现象。Massive MIMO 把它放大到 64 维:每根天线的相位是一个旋钮,调好这 64 个旋钮,就能让所有波在你这个点相加,在别的点互相抵消。手机之所以收得到信号,是因为 64 个射出去的波恰好在你手机这一寸空间里"相长干涉"。 -这本质上是数学上的相干叠加。基站要根据测得的信道矩阵 H,计算出一个加权矩阵 W,使得发射信号 s 在你的位置上能量最大: +这本质上是数学上的相干叠加。基站要根据测得的信道矩阵 H,计算出一个加权矩阵 W,使得发射信号 s 在你的位置上能量最大: ``` y = HWs + n ``` -其中 y 是你的手机收到的信号,n 是噪声。要选合适的 W,常用的方法有: +其中 y 是你的手机收到的信号,n 是噪声。要选合适的 W,常用的方法有: -- **最大比合并(MRC)**:W = H^H(H 的共轭转置) +- **最大比合并(MRC)**:W = H^H(H 的共轭转置) - **迫零(ZF)**:W = (H^H × H)⁻¹ × H^H -- **MMSE**(最小均方误差):在 ZF 基础上考虑噪声,对小奇异值不那么"狠" +- **MMSE**(最小均方误差):在 ZF 基础上考虑噪声,对小奇异值不那么"狠" -这些都是矩阵运算,基站里有专门的 DSP 或 FPGA 加速。 +这些都是矩阵运算,基站里有专门的 DSP 或 FPGA 加速。 ### 4.3 BBU 里发生的事 -BBU 收到 AAU 送来的信号后,做的事情和你的手机基带芯片做的事情正好反过来:解调、解扰、信道解码、CRC 校验、最后还原出原始的数据包。 +BBU 收到 AAU 送来的信号后,做的事情和你的手机基带芯片做的事情正好反过来:解调、解扰、信道解码、CRC 校验、最后还原出原始的数据包。 -如果 **CRC 校验**失败,基站会发一个 **NACK**(否定确认)给手机,触发 **HARQ**(混合自动重传请求):手机不会简单地把整个包重新发一遍,而是把不同的"冗余版本"发过去。基站把多次收到的版本合并解码——这叫"软合并",比单纯重传效率高得多。 +如果 **CRC 校验**失败,基站会发一个 **NACK**(否定确认)给手机,触发 **HARQ**(混合自动重传请求):手机不会简单地把整个包重新发一遍,而是把不同的"冗余版本"发过去。基站把多次收到的版本合并解码——这叫"软合并",比单纯重传效率高得多。 -CRC 校验通过后,数据包从物理层往上走,经过 MAC 层、RLC 层、PDCP 层、SDAP 层(这些都是 5G 协议栈的层级),最终交给 5G 核心网。 +CRC 校验通过后,数据包从物理层往上走,经过 MAC 层、RLC 层、PDCP 层、SDAP 层(这些都是 5G 协议栈的层级),最终交给 5G 核心网。 ### 4.4 5G 核心网 -5G 核心网(5GC)是一组运行在云上的网络功能(NF),包括: +5G 核心网(5GC)是一组运行在云上的网络功能(NF),包括: -- **AMF**(接入和移动性管理):管你的手机注册、鉴权、移动切换 -- **SMF**(会话管理):管你的数据会话 -- **UPF**(用户面功能):真正转发你的数据包 +- **AMF**(接入和移动性管理):管你的手机注册、鉴权、移动切换 +- **SMF**(会话管理):管你的数据会话 +- **UPF**(用户面功能):真正转发你的数据包 -你的数据包经过基站之后,会走一条 GTP 隧道(GPRS 隧道协议)到达 UPF。UPF 把外层的隧道头剥掉,露出原本的 IP 包(目的地是 `142.250.71.46`),然后通过运营商的路由器转发出去。 +你的数据包经过基站之后,会走一条 GTP 隧道(GPRS 隧道协议)到达 UPF。UPF 把外层的隧道头剥掉,露出原本的 IP 包(目的地是 `142.250.71.46`),然后通过运营商的路由器转发出去。 -到这里,你的数据包终于"进入了互联网"。 +到这里,你的数据包终于"进入了互联网"。 -**这一章的物理 / 数学**:波的相干干涉(双缝实验级别的物理) → Massive MIMO 波束赋形;线性代数 / 矩阵伪逆 → MRC、ZF、MMSE 的求解;CRC 多项式除法(GF(2) 上)→ 错误检测;HARQ 软合并 → 多次接收信号的统计累积(信噪比相加,在信息论里叫"互信息累积")。 +**这一章的物理 / 数学**:波的相干干涉(双缝实验级别的物理) → Massive MIMO 波束赋形;线性代数 / 矩阵伪逆 → MRC、ZF、MMSE 的求解;CRC 多项式除法(GF(2) 上)→ 错误检测;HARQ 软合并 → 多次接收信号的统计累积(信噪比相加,在信息论里叫"互信息累积")。 --- -## 第 5 章 城域网与骨干网:光纤里的高速公路 +## 第 5 章 城域网与骨干网:光纤里的高速公路 ### 5.1 数据包出了 UPF 之后 -UPF 的位置通常在运营商的城域网入口。从这里开始,你的数据包要经过几层路由器: +UPF 的位置通常在运营商的城域网入口。从这里开始,你的数据包要经过几层路由器: ``` UPF @@ -377,144 +377,144 @@ UPF → 国际出口 ``` -每经过一台路由器,有几件事发生: +每经过一台路由器,有几件事发生: -1. 路由器收到一个以太网帧,剥掉以太网头,看到 IP 头。 +1. 路由器收到一个以太网帧,剥掉以太网头,看到 IP 头。 2. 看 IP 头里的目的地址 `142.250.71.46`。 3. 在自己的路由表里查这个地址应该往哪里转发。 -4. 把 IP 头里的 TTL(生存时间)减 1,重算 IP 头校验和。 -5. 重新封装一个新的以太网头(下一跳的 MAC 地址),从对应的端口发出去。 +4. 把 IP 头里的 TTL(生存时间)减 1,重算 IP 头校验和。 +5. 重新封装一个新的以太网头(下一跳的 MAC 地址),从对应的端口发出去。 -这个过程叫"路由转发",每经过一跳大约耗时几十微秒。 +这个过程叫"路由转发",每经过一跳大约耗时几十微秒。 ### 5.2 路由器是怎么做到线速转发的 -一台运营商核心路由器(比如华为 NE9000、思科 ASR 9000)的处理能力是恐怖的:每秒处理几亿到几十亿个数据包。这种速度普通 CPU 是绝对达不到的,靠的是专用的转发 ASIC(专用集成电路)。 +一台运营商核心路由器(比如华为 NE9000、思科 ASR 9000)的处理能力是恐怖的:每秒处理几亿到几十亿个数据包。这种速度普通 CPU 是绝对达不到的,靠的是专用的转发 ASIC(专用集成电路)。 -路由器内部一般是这样的架构: +路由器内部一般是这样的架构: -- **线卡**:每张线卡有几十个端口,每个端口连一根光纤。线卡上有自己的转发 ASIC 和内存。 -- **背板**:把所有线卡连起来的高速交换矩阵。 -- **主控板**:跑路由协议(BGP、OSPF 等),计算路由表。 -- **TCAM**(三态内容寻址存储器):一种特殊的内存,可以并行匹配大量规则,做"最长前缀匹配"非常快。 +- **线卡**:每张线卡有几十个端口,每个端口连一根光纤。线卡上有自己的转发 ASIC 和内存。 +- **背板**:把所有线卡连起来的高速交换矩阵。 +- **主控板**:跑路由协议(BGP、OSPF 等),计算路由表。 +- **TCAM**(三态内容寻址存储器):一种特殊的内存,可以并行匹配大量规则,做"最长前缀匹配"非常快。 -路由表查找的核心算法叫"最长前缀匹配"(Longest Prefix Match)。比如目的 IP 是 `142.250.71.46`,路由表里可能有: +路由表查找的核心算法叫"最长前缀匹配"(Longest Prefix Match)。比如目的 IP 是 `142.250.71.46`,路由表里可能有: - `142.250.0.0/16` → 出口 A - `142.250.71.0/24` → 出口 B -- `0.0.0.0/0`(默认路由) → 出口 C +- `0.0.0.0/0`(默认路由) → 出口 C -应该选最长(最具体)的那条,也就是 `142.250.71.0/24` → 出口 B。TCAM 能在一个时钟周期内并行比较所有条目,找出最匹配的。 +应该选最长(最具体)的那条,也就是 `142.250.71.0/24` → 出口 B。TCAM 能在一个时钟周期内并行比较所有条目,找出最匹配的。 -### 5.3 路由协议:路由表怎么来的 +### 5.3 路由协议:路由表怎么来的 -路由器的转发表不是手动配的,而是路由协议自动算出来的。运营商内部用 **OSPF** 或 **IS-IS**(都是基于 **Dijkstra 最短路径**的链路状态协议),运营商之间用 **BGP(边界网关协议)**(本质上是一种"路径向量"协议,加了大量人为策略)。 +路由器的转发表不是手动配的,而是路由协议自动算出来的。运营商内部用 **OSPF** 或 **IS-IS**(都是基于 **Dijkstra 最短路径**的链路状态协议),运营商之间用 **BGP(边界网关协议)**(本质上是一种"路径向量"协议,加了大量人为策略)。 -简单说:整个互联网是几万个"自治系统"(AS,Autonomous System)拼起来的,每个 AS 有一个号(中国电信是 AS4134,Google 是 AS15169)。BGP 让 AS 之间互相宣告"我能到哪些 IP 段",每个 AS 根据收到的信息选出"到任意目的地的最佳路径"——所以整个互联网的路径选择,本质是**图论里的最短 / 最优路径问题**叠上了商业关系策略层。 +简单说:整个互联网是几万个"自治系统"(AS,Autonomous System)拼起来的,每个 AS 有一个号(中国电信是 AS4134,Google 是 AS15169)。BGP 让 AS 之间互相宣告"我能到哪些 IP 段",每个 AS 根据收到的信息选出"到任意目的地的最佳路径"——所以整个互联网的路径选择,本质是**图论里的最短 / 最优路径问题**叠上了商业关系策略层。 -到这里,你的数据包正在从中国的某个城市的一台路由器,跳着跳着前往海岸线。 +到这里,你的数据包正在从中国的某个城市的一台路由器,跳着跳着前往海岸线。 ### 5.4 光纤里的物理传输 -路由器之间用光纤连接,长距离链路用 **DWDM(密集波分复用)** 技术——把好几十个不同波长的激光复用在同一根光纤里同时传输,容量倍增。 +路由器之间用光纤连接,长距离链路用 **DWDM(密集波分复用)** 技术——把好几十个不同波长的激光复用在同一根光纤里同时传输,容量倍增。 -光纤本身是一根头发丝粗细的玻璃纤维,中心是高折射率的纤芯,外层是低折射率的包层。光在纤芯里靠**全反射**传播,几乎不损耗——好的单模光纤衰减只有 0.2 dB/km(意思是 100km 后信号还剩约 1%)。 +光纤本身是一根头发丝粗细的玻璃纤维,中心是高折射率的纤芯,外层是低折射率的包层。光在纤芯里靠**全反射**传播,几乎不损耗——好的单模光纤衰减只有 0.2 dB/km(意思是 100km 后信号还剩约 1%)。 -全反射靠的是 **斯涅尔定律(Snell's Law)**: +全反射靠的是 **斯涅尔定律(Snell's Law)**: ``` n₁ × sin(θ₁) = n₂ × sin(θ₂) ``` -当光从高折射率介质(n₁)射向低折射率介质(n₂)时,如果入射角足够大,折射角会变成 90° 甚至更大,光就被"反射"回来了。这个临界角是 `θ_c = arcsin(n₂/n₁)`。 +当光从高折射率介质(n₁)射向低折射率介质(n₂)时,如果入射角足够大,折射角会变成 90° 甚至更大,光就被"反射"回来了。这个临界角是 `θ_c = arcsin(n₂/n₁)`。 -**光到底是什么**:**Maxwell 方程组**给出的视角是"传播中的电磁波";**量子力学**给出的视角是"一份份能量包,叫光子(photon)"。一个光子的能量是 `E = h × f`(**普朗克常数** × 频率,**马克斯·普朗克(Max Planck)** 1900 年提出),通信常用的 1550 nm 波长,单个光子能量约 0.8 eV ≈ 1.3 × 10⁻¹⁹ 焦耳。一根 100 Gbps 光纤每秒大约要发 10²⁰ 量级的光子。光的"波动性"(Maxwell)和"粒子性"(光子)在不同尺度上各自适用——光纤里的传播用 Maxwell 算最方便,EDFA 放大的过程必须用量子语言才能讲清。 +**光到底是什么**:**Maxwell 方程组**给出的视角是"传播中的电磁波";**量子力学**给出的视角是"一份份能量包,叫光子(photon)"。一个光子的能量是 `E = h × f`(**普朗克常数** × 频率,**马克斯·普朗克(Max Planck)** 1900 年提出),通信常用的 1550 nm 波长,单个光子能量约 0.8 eV ≈ 1.3 × 10⁻¹⁹ 焦耳。一根 100 Gbps 光纤每秒大约要发 10²⁰ 量级的光子。光的"波动性"(Maxwell)和"粒子性"(光子)在不同尺度上各自适用——光纤里的传播用 Maxwell 算最方便,EDFA 放大的过程必须用量子语言才能讲清。 -光信号传几十公里就会衰减,所以每隔一段距离要加一个**光放大器**。最常用的是 **EDFA(掺铒光纤放大器)**,原理是给一段掺了铒元素的光纤通入泵浦激光,让铒离子被激发,经过的信号光会触发**受激辐射**,从而被放大——整个过程是纯光学的,不需要"光转电再转光",速度快、噪声低。 +光信号传几十公里就会衰减,所以每隔一段距离要加一个**光放大器**。最常用的是 **EDFA(掺铒光纤放大器)**,原理是给一段掺了铒元素的光纤通入泵浦激光,让铒离子被激发,经过的信号光会触发**受激辐射**,从而被放大——整个过程是纯光学的,不需要"光转电再转光",速度快、噪声低。 -**EDFA 的量子物理再拆一层**:铒离子(Er³⁺)的电子有几个能级。泵浦激光(典型 980nm 或 1480nm)把电子从低能级"打"到高能级,这叫**粒子数反转**——正常情况下电子都呆在低能级,反转之后高能级反而塞满了。当一个 1550nm 的信号光子穿过这段光纤时,它会"诱导"高能级的电子掉下来,掉下来时多放出一个**和入射光子一模一样的光子**(频率、相位、方向、偏振全相同)——这就是 **阿尔伯特·爱因斯坦(Albert Einstein)** 1917 年提出的**受激辐射(stimulated emission)**,激光的"LASER"里那个 SE 就是它。一来一回,光子数翻倍。所以 EDFA 不是把光"加亮",而是把光子"复制"。这条原理同样支撑着所有激光器、光通信、原子钟。 +**EDFA 的量子物理再拆一层**:铒离子(Er³⁺)的电子有几个能级。泵浦激光(典型 980nm 或 1480nm)把电子从低能级"打"到高能级,这叫**粒子数反转**——正常情况下电子都呆在低能级,反转之后高能级反而塞满了。当一个 1550nm 的信号光子穿过这段光纤时,它会"诱导"高能级的电子掉下来,掉下来时多放出一个**和入射光子一模一样的光子**(频率、相位、方向、偏振全相同)——这就是 **阿尔伯特·爱因斯坦(Albert Einstein)** 1917 年提出的**受激辐射(stimulated emission)**,激光的"LASER"里那个 SE 就是它。一来一回,光子数翻倍。所以 EDFA 不是把光"加亮",而是把光子"复制"。这条原理同样支撑着所有激光器、光通信、原子钟。 ### 5.5 海底电缆登场 -如果你的目的地是 Google,而 Google 的服务器在美国,那你的数据包要通过海底电缆出国。 +如果你的目的地是 Google,而 Google 的服务器在美国,那你的数据包要通过海底电缆出国。 -中国大陆有几条主要的海底电缆出口,大部分集中在上海(崇明、南汇)、青岛、汕头。通往美国的主要电缆有 TPE(跨太平洋快线)、APG(亚太直达海缆)、NCP(新跨太平洋海缆)等。 +中国大陆有几条主要的海底电缆出口,大部分集中在上海(崇明、南汇)、青岛、汕头。通往美国的主要电缆有 TPE(跨太平洋快线)、APG(亚太直达海缆)、NCP(新跨太平洋海缆)等。 -**这一章的物理 / 数学**:Maxwell 方程组(光是电磁波)+ 折射定律(斯涅尔)→ 光纤全反射;光子能量 `E = hf`(量子)→ 单光子级别的极限灵敏度;受激辐射(爱因斯坦,1917)→ EDFA 全光放大;BGP 路径选择 → 图论上的最短/最优路径问题;TCAM 最长前缀匹配 → 字典树(trie)的硬件并行化版本。 +**这一章的物理 / 数学**:Maxwell 方程组(光是电磁波)+ 折射定律(斯涅尔)→ 光纤全反射;光子能量 `E = hf`(量子)→ 单光子级别的极限灵敏度;受激辐射(爱因斯坦,1917)→ EDFA 全光放大;BGP 路径选择 → 图论上的最短/最优路径问题;TCAM 最长前缀匹配 → 字典树(trie)的硬件并行化版本。 --- -## 第 6 章 GFW 与翻墙:一场 HTTPS 拟态的猫鼠游戏 +## 第 6 章 GFW 与翻墙:一场 HTTPS 拟态的猫鼠游戏 -> 前 5 章讲的是全球通用的链路;这一章专门讲中国大陆的特殊关口——**国际出口处的 GFW**,以及它催生出的一整套"HTTPS 拟态"工程。如果你只关心通用原理,可以直接跳第 7 章;但里面有几个工程巧思(用真实 TLS 握手做掩护、对探测请求原样转发)非常值得一读,密码学之外还能看到博弈论是怎么落地的。 +> 前 5 章讲的是全球通用的链路;这一章专门讲中国大陆的特殊关口——**国际出口处的 GFW**,以及它催生出的一整套"HTTPS 拟态"工程。如果你只关心通用原理,可以直接跳第 7 章;但里面有几个工程巧思(用真实 TLS 握手做掩护、对探测请求原样转发)非常值得一读,密码学之外还能看到博弈论是怎么落地的。 ### 6.1 GFW 是什么、装在哪里 -**GFW(Great Firewall,防火长城)** 不是一台机器,而是一组分布式部署在中国国家级骨干网与国际出口处的旁路审查设备 + 主动探测系统的总称。 +**GFW(Great Firewall,防火长城)** 不是一台机器,而是一组分布式部署在中国国家级骨干网与国际出口处的旁路审查设备 + 主动探测系统的总称。 -它的物理位置在 §5.1 那张转发链的尾端——城域网汇聚到骨干网,骨干网再汇聚到国际出口路由器,GFW 就接在这些出口路由器**旁边**。注意是"旁边"不是"路上":真正的转发不经过 GFW(否则一坏整个国家断网),GFW 用光分路器把所有过境流量复制一份去做镜像分析。它检测到违规就在路径上**注入伪造的 RST 包**把 TCP 连接撕掉,或者通知上游设备做 BGP 黑洞、ACL 丢包。 +它的物理位置在 §5.1 那张转发链的尾端——城域网汇聚到骨干网,骨干网再汇聚到国际出口路由器,GFW 就接在这些出口路由器**旁边**。注意是"旁边"不是"路上":真正的转发不经过 GFW(否则一坏整个国家断网),GFW 用光分路器把所有过境流量复制一份去做镜像分析。它检测到违规就在路径上**注入伪造的 RST 包**把 TCP 连接撕掉,或者通知上游设备做 BGP 黑洞、ACL 丢包。 -它的能力大致这几样: +它的能力大致这几样: -- **DNS 污染 / 投毒**:对敏感域名,GFW 比真权威 DNS 服务器**更早一步**把伪造答案塞回来。你查 `www.google.com`,可能秒收到一个根本不是 Google 的 IP(比如某个保留地址或随机大站 IP);真答案要么晚到、要么压根到不了。原理是 GFW 在路径上"抢答"——DNS 默认走 UDP 53,无连接、无加密、无认证,谁的回包先到谁就赢 -- **IP 黑名单 / 路由黑洞**:已知敏感 IP 段在国家路由器上直接 BGP 黑洞或 null-routed,丢包率 100% -- **SNI 探测**:你 §9.1 学到的 ClientHello 里的 **SNI(Server Name Indication)是明文**的——GFW 直接读 SNI 字段,看到 `www.google.com` 就发 RST。这是当前最主要的拦截手段 -- **协议指纹 / TLS ClientHello 指纹**:即使加密了内容,不同 TLS 实现(Chrome / Firefox / OpenSSL / Go / Python)产生的 ClientHello 在字段顺序、扩展项、密码套件列表上会留下"指纹",GFW 用这个识别"非主流客户端" -- **主动探测**:对可疑的服务器 IP,GFW 会主动去握手——如果你的服务器对一个伪造的探测请求"露馅"(响应了不该响应的协议格式),就被加进黑名单 -- **时序与流量分析**:即使内容完全加密、协议完全正常,流量的包大小分布、发包间隔、上下行比例、连接持续时间本身就是特征——视频流、网页浏览、SSH、代理各有典型形态 +- **DNS 污染 / 投毒**:对敏感域名,GFW 比真权威 DNS 服务器**更早一步**把伪造答案塞回来。你查 `www.google.com`,可能秒收到一个根本不是 Google 的 IP(比如某个保留地址或随机大站 IP);真答案要么晚到、要么压根到不了。原理是 GFW 在路径上"抢答"——DNS 默认走 UDP 53,无连接、无加密、无认证,谁的回包先到谁就赢 +- **IP 黑名单 / 路由黑洞**:已知敏感 IP 段在国家路由器上直接 BGP 黑洞或 null-routed,丢包率 100% +- **SNI 探测**:你 §9.1 学到的 ClientHello 里的 **SNI(Server Name Indication)是明文**的——GFW 直接读 SNI 字段,看到 `www.google.com` 就发 RST。这是当前最主要的拦截手段 +- **协议指纹 / TLS ClientHello 指纹**:即使加密了内容,不同 TLS 实现(Chrome / Firefox / OpenSSL / Go / Python)产生的 ClientHello 在字段顺序、扩展项、密码套件列表上会留下"指纹",GFW 用这个识别"非主流客户端" +- **主动探测**:对可疑的服务器 IP,GFW 会主动去握手——如果你的服务器对一个伪造的探测请求"露馅"(响应了不该响应的协议格式),就被加进黑名单 +- **时序与流量分析**:即使内容完全加密、协议完全正常,流量的包大小分布、发包间隔、上下行比例、连接持续时间本身就是特征——视频流、网页浏览、SSH、代理各有典型形态 -把它当成一个**国家级的分布式入侵检测系统(IDS)** 来看就好——本质上是 DPI(深度包检测)+ 主动探测 + BGP 黑洞 联动。 +把它当成一个**国家级的分布式入侵检测系统(IDS)** 来看就好——本质上是 DPI(深度包检测)+ 主动探测 + BGP 黑洞 联动。 -### 6.2 不翻墙时,访问 Google 会被打在哪几层 +### 6.2 不翻墙时,访问 Google 会被打在哪几层 -如果不做任何处理,直接在国内访问 `www.google.com`,前面那条链路会被 GFW 在三个不同层面打断: +如果不做任何处理,直接在国内访问 `www.google.com`,前面那条链路会被 GFW 在三个不同层面打断: -- **DNS 层**:`www.google.com → ?` 查询往外发,GFW 投毒,你拿到一个错的 IP。如果你想绕开用 8.8.8.8(Google 公共 DNS),DNS over UDP 53 同样被污染,DNS over HTTPS / DoT 走 443 / 853 又会因为 SNI / IP 被另外打 -- **IP / TCP 层**:就算你硬编码了 Google 真实 IP,§8.2 的 SYN 包出去后,GFW 在路径上注入 RST,TCP 连接刚握手就被切断 -- **TLS 层**:就算 SYN 侥幸通了,§9.1 的 ClientHello 一发出去,SNI 里写着 `www.google.com`,GFW 立刻从旁路注入 RST +- **DNS 层**:`www.google.com → ?` 查询往外发,GFW 投毒,你拿到一个错的 IP。如果你想绕开用 8.8.8.8(Google 公共 DNS),DNS over UDP 53 同样被污染,DNS over HTTPS / DoT 走 443 / 853 又会因为 SNI / IP 被另外打 +- **IP / TCP 层**:就算你硬编码了 Google 真实 IP,§8.2 的 SYN 包出去后,GFW 在路径上注入 RST,TCP 连接刚握手就被切断 +- **TLS 层**:就算 SYN 侥幸通了,§9.1 的 ClientHello 一发出去,SNI 里写着 `www.google.com`,GFW 立刻从旁路注入 RST 三层任意一层中招就完蛋。所以**翻墙的本质就是在这三层都让 GFW 看不出你想去哪**。 -### 6.3 翻墙小史:从 Shadowsocks 到 Reality +### 6.3 翻墙小史:从 Shadowsocks 到 Reality -每一代翻墙协议都是对当时 GFW 的针对性回应,演化轨迹本身就是一段精彩的猫鼠游戏: +每一代翻墙协议都是对当时 GFW 的针对性回应,演化轨迹本身就是一段精彩的猫鼠游戏: -- **Shadowsocks(2012)**:把流量用对称加密包一层,看起来像"无规律高熵字节流"。早期 GFW 只看明文特征,SS 一度无敌。但后来 GFW 学会了识别"过于随机的流量"——正常协议都有协议头,SS 没有,这本身就是一种特征 -- **V2Ray VMess(2016)**:加更多伪装,但 VMess 自己设计的协议头有可识别特征,后来也被打 -- **Trojan(2017)**:思路反转——别假装"不是协议",直接**假装是标准 HTTPS**。Trojan 服务端跑一个真 nginx,认证失败就把流量真的转发给 nginx 返回正经网页。这一招让 GFW 的主动探测失效。但 Trojan 客户端的 TLS 库指纹(Go 标准库)和主流浏览器不一样,被识别 -- **VLESS + TLS + Vision(2022)**:用 **uTLS** 库精确模拟 Chrome 的 TLS 指纹,XTLS Vision 减少加密层数提升性能。已经很难被识别,但需要自己有域名 + 申请 Let's Encrypt 证书 -- **Reality(2023)**:**把伪装推到了极致——不再自己造 TLS 证书,直接借一个真实大网站的握手**。从 GFW 的角度看,你和服务器之间在密码学层面看到的握手内容,和你直接访问那个大网站完全一致;Reality 自己的认证发生在数据流深处,GFW 看不到。 +- **Shadowsocks(2012)**:把流量用对称加密包一层,看起来像"无规律高熵字节流"。早期 GFW 只看明文特征,SS 一度无敌。但后来 GFW 学会了识别"过于随机的流量"——正常协议都有协议头,SS 没有,这本身就是一种特征 +- **V2Ray VMess(2016)**:加更多伪装,但 VMess 自己设计的协议头有可识别特征,后来也被打 +- **Trojan(2017)**:思路反转——别假装"不是协议",直接**假装是标准 HTTPS**。Trojan 服务端跑一个真 nginx,认证失败就把流量真的转发给 nginx 返回正经网页。这一招让 GFW 的主动探测失效。但 Trojan 客户端的 TLS 库指纹(Go 标准库)和主流浏览器不一样,被识别 +- **VLESS + TLS + Vision(2022)**:用 **uTLS** 库精确模拟 Chrome 的 TLS 指纹,XTLS Vision 减少加密层数提升性能。已经很难被识别,但需要自己有域名 + 申请 Let's Encrypt 证书 +- **Reality(2023)**:**把伪装推到了极致——不再自己造 TLS 证书,直接借一个真实大网站的握手**。从 GFW 的角度看,你和服务器之间在密码学层面看到的握手内容,和你直接访问那个大网站完全一致;Reality 自己的认证发生在数据流深处,GFW 看不到。 每一代都是对前一代被识别点的修补。Reality 是这条线上目前的"最优解"。 -### 6.4 Reality 工作原理:借壳的 TLS +### 6.4 Reality 工作原理:借壳的 TLS -Reality 的核心思路一句话:**让代理流量在 TLS 层面和"访问一个真实大站"无法区分**。具体怎么做的—— +Reality 的核心思路一句话:**让代理流量在 TLS 层面和"访问一个真实大站"无法区分**。具体怎么做的—— -**1. 借壳:握手目标写真实大站的 SNI** +**1. 借壳:握手目标写真实大站的 SNI** -部署 Reality 时要选一个"借壳目标"(target),通常是一个**网络上必然存在、政治上不可能被封、TLS 实现强壮**的大站,比如 `dl.microsoft.com`、`www.cloudflare.com`、`addons.mozilla.org`。 +部署 Reality 时要选一个"借壳目标"(target),通常是一个**网络上必然存在、政治上不可能被封、TLS 实现强壮**的大站,比如 `dl.microsoft.com`、`www.cloudflare.com`、`addons.mozilla.org`。 -客户端发起连接时,§9.1 那个 ClientHello 里的 SNI 字段写的就是 `dl.microsoft.com`——**注意,这是真的写,不是假装**。GFW 看到这个 SNI,行为上和你真的去访问微软完全一样,放行。 +客户端发起连接时,§9.1 那个 ClientHello 里的 SNI 字段写的就是 `dl.microsoft.com`——**注意,这是真的写,不是假装**。GFW 看到这个 SNI,行为上和你真的去访问微软完全一样,放行。 -**2. X25519 暗号:对得上才解密,对不上原样转发** +**2. X25519 暗号:对得上才解密,对不上原样转发** -客户端 ClientHello 里塞一个用预先共享的服务端公钥(X25519 椭圆曲线)算出来的"暗号"(藏在 ClientHello 的随机字段里,从外面看就是普通的随机数)。服务器收到后,用自己的私钥验证这个暗号: +客户端 ClientHello 里塞一个用预先共享的服务端公钥(X25519 椭圆曲线)算出来的"暗号"(藏在 ClientHello 的随机字段里,从外面看就是普通的随机数)。服务器收到后,用自己的私钥验证这个暗号: -- **验证通过**:这是合法 Reality 客户端,服务器进入 Reality 协议,后面解密承载的真实代理流量 -- **验证失败**(或者根本没暗号——主动探测最常见):**服务器把这条 TCP 连接整体透明转发给真实的 `dl.microsoft.com`,自己什么都不做**。GFW 主动探测看到的会是**微软的真实响应、真实证书、真实页面** +- **验证通过**:这是合法 Reality 客户端,服务器进入 Reality 协议,后面解密承载的真实代理流量 +- **验证失败**(或者根本没暗号——主动探测最常见):**服务器把这条 TCP 连接整体透明转发给真实的 `dl.microsoft.com`,自己什么都不做**。GFW 主动探测看到的会是**微软的真实响应、真实证书、真实页面** -这一步是 Reality 最聪明的地方:**主动探测是 GFW 的杀手锏,Reality 直接把它变成"探测必看到合法网站",从而无效化**。 +这一步是 Reality 最聪明的地方:**主动探测是 GFW 的杀手锏,Reality 直接把它变成"探测必看到合法网站",从而无效化**。 **3. 证书链也是真的** -更狠的是,Reality 服务器返回给客户端的 TLS 证书链,**就是从那个真实大站抓来的真证书**(只不过签名部分被替换,客户端跳过验证而已)。所以即使 GFW 想做"证书指纹"——比如检测自签证书、检测某些可疑 CA——它看到的也是微软的合法证书,无懈可击。 +更狠的是,Reality 服务器返回给客户端的 TLS 证书链,**就是从那个真实大站抓来的真证书**(只不过签名部分被替换,客户端跳过验证而已)。所以即使 GFW 想做"证书指纹"——比如检测自签证书、检测某些可疑 CA——它看到的也是微软的合法证书,无懈可击。 **4. uTLS 模拟主流浏览器指纹** -ClientHello 的扩展顺序、密码套件列表用 **uTLS 库**精确模拟 Chrome / Firefox / Safari 的指纹,GFW 没法靠"TLS 实现指纹"判别这是不是浏览器流量。 +ClientHello 的扩展顺序、密码套件列表用 **uTLS 库**精确模拟 Chrome / Firefox / Safari 的指纹,GFW 没法靠"TLS 实现指纹"判别这是不是浏览器流量。 -**5. 加上 Reality 后,数据包的真实路径** +**5. 加上 Reality 后,数据包的真实路径** ``` 浏览器 @@ -533,210 +533,210 @@ ClientHello 的扩展顺序、密码套件列表用 **uTLS 库**精确模拟 Chr → 解密后交给浏览器 ``` -注意一个关键事实:**真正的目标(Google)在 GFW 视野里从未出现过**。GFW 看到的全程都是"国内某 IP 在和 dl.microsoft.com 进行一次正常 HTTPS 通信",该 SNI、该证书、该指纹一切合法。 +注意一个关键事实:**真正的目标(Google)在 GFW 视野里从未出现过**。GFW 看到的全程都是"国内某 IP 在和 dl.microsoft.com 进行一次正常 HTTPS 通信",该 SNI、该证书、该指纹一切合法。 ### 6.5 Reality 的安全建立在哪里 -如果纯从密码学讲,Reality 的"暗号"机制并不比常规 TLS 更强。它真正的安全性建立在一个**非密码学事实**上: +如果纯从密码学讲,Reality 的"暗号"机制并不比常规 TLS 更强。它真正的安全性建立在一个**非密码学事实**上: -**GFW 不敢真断借壳目标(像 microsoft.com)的访问**。 +**GFW 不敢真断借壳目标(像 microsoft.com)的访问**。 -只要这条假设成立,GFW 就不能简单地"宁错杀一千"——封 Reality 等于连带把微软封了,这是政治和商业上都不可接受的。Reality 把"是不是代理流量"这个判别问题,转化成了"是不是 microsoft.com 流量",而后者是 GFW 主动放过的。 +只要这条假设成立,GFW 就不能简单地"宁错杀一千"——封 Reality 等于连带把微软封了,这是政治和商业上都不可接受的。Reality 把"是不是代理流量"这个判别问题,转化成了"是不是 microsoft.com 流量",而后者是 GFW 主动放过的。 这是一个**密码学 + 工程 + 博弈论**三者结合的设计。单看任何一层都讲不全。 ### 6.6 还在继续的猫鼠游戏 -Reality 不是终点。审查与反审查的对抗还在每一层继续: +Reality 不是终点。审查与反审查的对抗还在每一层继续: -- **TLS ECH(Encrypted Client Hello)**:IETF 推动的标准,把 SNI 也加密,从根上解决 SNI 明文泄露的问题。原理是用一个公开的"外层 SNI"(指向 CDN 大入口)做 TLS,再在里面加密承载真实 SNI。听起来很美好,但 **GFW 已经在 2024 年开始对启用 ECH 的连接做选择性丢包**——一手反制就是"启用 ECH = 可疑指纹",直接掐。这一步把 ECH 想解决的问题(SNI 明文)反而变成了"启用 ECH 就被识别"的新问题 -- **流量整形 / 时序分析**:即使内容完全像 microsoft.com,实际行为模式可能不像——比如 Reality 隧道开了 30 分钟没断、上下行比例稳定 1:8 像在看视频,但真去微软网站的人很少这么干。GFW 在做这类**行为指纹**分析。Reality / Xray 的应对是引入**流量填充(padding)** 和**包间隔随机化**,让流量分布更接近真实浏览。但这是博弈不是定论 -- **量子计算的远期威胁**:§9.2 提到过——Shor 算法理论上能破 X25519 等基于离散对数的密码原语。如果有一天大规模量子计算成熟,Reality 用的暗号机制要跟着升级到后量子算法。这是未来 5-15 年的悬剑 -- **机器学习侧**:近年 GFW 据传也在用机器学习模型做流量分类——给定一段加密流量,模型直接输出"这是浏览网页 / 视频 / SSH / 代理"的概率分布。这是一条全新的战线,反制的思路必然涉及对抗样本、流量混淆生成模型这些更复杂的工具 +- **TLS ECH(Encrypted Client Hello)**:IETF 推动的标准,把 SNI 也加密,从根上解决 SNI 明文泄露的问题。原理是用一个公开的"外层 SNI"(指向 CDN 大入口)做 TLS,再在里面加密承载真实 SNI。听起来很美好,但 **GFW 已经在 2024 年开始对启用 ECH 的连接做选择性丢包**——一手反制就是"启用 ECH = 可疑指纹",直接掐。这一步把 ECH 想解决的问题(SNI 明文)反而变成了"启用 ECH 就被识别"的新问题 +- **流量整形 / 时序分析**:即使内容完全像 microsoft.com,实际行为模式可能不像——比如 Reality 隧道开了 30 分钟没断、上下行比例稳定 1:8 像在看视频,但真去微软网站的人很少这么干。GFW 在做这类**行为指纹**分析。Reality / Xray 的应对是引入**流量填充(padding)** 和**包间隔随机化**,让流量分布更接近真实浏览。但这是博弈不是定论 +- **量子计算的远期威胁**:§9.2 提到过——Shor 算法理论上能破 X25519 等基于离散对数的密码原语。如果有一天大规模量子计算成熟,Reality 用的暗号机制要跟着升级到后量子算法。这是未来 5-15 年的悬剑 +- **机器学习侧**:近年 GFW 据传也在用机器学习模型做流量分类——给定一段加密流量,模型直接输出"这是浏览网页 / 视频 / SSH / 代理"的概率分布。这是一条全新的战线,反制的思路必然涉及对抗样本、流量混淆生成模型这些更复杂的工具 -**这一章的物理 / 数学**:这一章的"敌人"不再是物理定律,而是另一组工程师。所有底层数学还是同一套(TLS、椭圆曲线、AES、SHA),但**真正的胜负发生在协议设计、流量模式、博弈假设、政治成本**这些层面。读完前面 8 章你知道"互联网怎么工作",读完这一章你才知道"它在敌对环境下怎么活下来"。 +**这一章的物理 / 数学**:这一章的"敌人"不再是物理定律,而是另一组工程师。所有底层数学还是同一套(TLS、椭圆曲线、AES、SHA),但**真正的胜负发生在协议设计、流量模式、博弈假设、政治成本**这些层面。读完前面 8 章你知道"互联网怎么工作",读完这一章你才知道"它在敌对环境下怎么活下来"。 --- -## 第 7 章 跨洋:海底电缆 +## 第 7 章 跨洋:海底电缆 ### 7.1 海底电缆的样子 -一根典型的跨洋光缆直径只有 2-3 厘米。从外到内的结构是: +一根典型的跨洋光缆直径只有 2-3 厘米。从外到内的结构是: - 聚乙烯外护套 - 聚酯树脂或沥青层 -- 钢丝铠装(在浅海段更厚,防渔船拖网和鲨鱼咬) +- 钢丝铠装(在浅海段更厚,防渔船拖网和鲨鱼咬) - 铝制防水层 - 聚碳酸酯绝缘层 -- 铜或铝管(用来给海底中继器供电) +- 铜或铝管(用来给海底中继器供电) - 凡士林防水 -- 中心是几对光纤(一般 4-16 对) +- 中心是几对光纤(一般 4-16 对) ### 7.2 海底中继器 -跨洋距离动辄几千甚至上万公里,光信号即使损耗很低也得放大。海底每隔 50-100 公里就有一个中继器,装在一个一两米长的金属圆柱里,沉在海底。 +跨洋距离动辄几千甚至上万公里,光信号即使损耗很低也得放大。海底每隔 50-100 公里就有一个中继器,装在一个一两米长的金属圆柱里,沉在海底。 -中继器内部主要是 EDFA 光放大器,靠从岸上通过光缆里的铜管供电——电压可以高达 ±15000V,这样长距离才不会损耗太多功率。 +中继器内部主要是 EDFA 光放大器,靠从岸上通过光缆里的铜管供电——电压可以高达 ±15000V,这样长距离才不会损耗太多功率。 ### 7.3 光纤里发生了什么 -你的数据包是一组激光脉冲。每个脉冲代表 0 或 1(实际上 100Gbps 以上的高速光通信用的是相干调制,比如 QPSK、16-QAM,一个符号编码多个比特)。 +你的数据包是一组激光脉冲。每个脉冲代表 0 或 1(实际上 100Gbps 以上的高速光通信用的是相干调制,比如 QPSK、16-QAM,一个符号编码多个比特)。 -光传播速度在光纤里大约是真空光速的 2/3,也就是 20 万公里每秒。从上海到美国西海岸大约 1 万公里光纤距离,单程就要 50 毫秒。再加上路由器排队、光电转换等,实际跨洋 RTT(往返时间)通常在 150-200 毫秒。 +光传播速度在光纤里大约是真空光速的 2/3,也就是 20 万公里每秒。从上海到美国西海岸大约 1 万公里光纤距离,单程就要 50 毫秒。再加上路由器排队、光电转换等,实际跨洋 RTT(往返时间)通常在 150-200 毫秒。 -光纤通信的关键挑战之一是色散——不同波长的光速度略有差别,长距离传输后脉冲会被"展宽",导致符号间干扰。现代相干光通信用 DSP(数字信号处理)在接收端补偿色散,这又是一堆复杂的数学。 +光纤通信的关键挑战之一是色散——不同波长的光速度略有差别,长距离传输后脉冲会被"展宽",导致符号间干扰。现代相干光通信用 DSP(数字信号处理)在接收端补偿色散,这又是一堆复杂的数学。 -### 7.4 物理层纠错:Reed-Solomon 和后续 +### 7.4 物理层纠错:Reed-Solomon 和后续 -海底光通信也需要前向纠错。常用的是 **Reed-Solomon 码**,典型配置是 RS(255, 239)——意思是每 239 字节数据加 16 字节校验,接收端可以纠正最多 8 个字节的错误。 +海底光通信也需要前向纠错。常用的是 **Reed-Solomon 码**,典型配置是 RS(255, 239)——意思是每 239 字节数据加 16 字节校验,接收端可以纠正最多 8 个字节的错误。 -**Reed-Solomon** 的数学原理是:把数据看作多项式的系数,在多个点求值得到码字;接收端如果某些点的值错了,根据剩下足够多的点重建多项式,从而恢复原始数据。这套方法是 **Irving S. Reed** 和 **Gustave Solomon** 1960 年发表的,后来在 CD/DVD/QR 码、卫星通信、深空探测里被反复用上。 +**Reed-Solomon** 的数学原理是:把数据看作多项式的系数,在多个点求值得到码字;接收端如果某些点的值错了,根据剩下足够多的点重建多项式,从而恢复原始数据。这套方法是 **Irving S. Reed** 和 **Gustave Solomon** 1960 年发表的,后来在 CD/DVD/QR 码、卫星通信、深空探测里被反复用上。 -现代高速光通信(400G/800G)用更高级的码,比如 SD-FEC(软判决 FEC),净编码增益接近 11dB。 +现代高速光通信(400G/800G)用更高级的码,比如 SD-FEC(软判决 FEC),净编码增益接近 11dB。 -**这一章的物理 / 数学**:光纤色散(不同波长光速不同 → 脉冲展宽)→ 接收端 DSP 数字补偿,本质是反卷积;Reed-Solomon(代数:把数据当多项式系数,在多个点求值,用拉格朗日插值反推)→ FEC 纠错的数学根;偏振 / 相干光通信(QPSK / 16-QAM 移植到光波)→ 光的"频谱效率"逼近香农极限;光放大噪声(自发辐射 ASE)→ 限制每段无中继距离。 +**这一章的物理 / 数学**:光纤色散(不同波长光速不同 → 脉冲展宽)→ 接收端 DSP 数字补偿,本质是反卷积;Reed-Solomon(代数:把数据当多项式系数,在多个点求值,用拉格朗日插值反推)→ FEC 纠错的数学根;偏振 / 相干光通信(QPSK / 16-QAM 移植到光波)→ 光的"频谱效率"逼近香农极限;光放大噪声(自发辐射 ASE)→ 限制每段无中继距离。 --- -## 第 8 章 TCP 三次握手:在虚拟世界里建立连接 +## 第 8 章 TCP 三次握手:在虚拟世界里建立连接 ### 8.1 数据包到了美国 -经过基站、运营商网络、海底电缆,你的数据包到达美国西海岸某个登陆站,然后通过美国国内的骨干网到达 Google 的某个数据中心(可能是俄勒冈州 The Dalles 的数据中心)。 +经过基站、运营商网络、海底电缆,你的数据包到达美国西海岸某个登陆站,然后通过美国国内的骨干网到达 Google 的某个数据中心(可能是俄勒冈州 The Dalles 的数据中心)。 -但其实在数据包能"传输 HTTP 内容"之前,先要建立 TCP 连接,然后做 TLS 握手。 +但其实在数据包能"传输 HTTP 内容"之前,先要建立 TCP 连接,然后做 TLS 握手。 ### 8.2 TCP 三次握手 -**TCP(传输控制协议)** 由 **Vint Cerf** 和 **Bob Kahn** 在 1974 年的论文里定义,它在不可靠的 IP 网络上提供可靠的、有序的、字节流式的通信。在传 HTTP 数据之前,要先用**三次握手**建立连接。 +**TCP(传输控制协议)** 由 **Vint Cerf** 和 **Bob Kahn** 在 1974 年的论文里定义,它在不可靠的 IP 网络上提供可靠的、有序的、字节流式的通信。在传 HTTP 数据之前,要先用**三次握手**建立连接。 -**第一次:客户端 → 服务器,SYN** +**第一次:客户端 → 服务器,SYN** -你的手机发一个 TCP 包,标志位 SYN(同步)= 1,带一个初始序号 `seq = x`(x 是随机数)。 +你的手机发一个 TCP 包,标志位 SYN(同步)= 1,带一个初始序号 `seq = x`(x 是随机数)。 -**第二次:服务器 → 客户端,SYN+ACK** +**第二次:服务器 → 客户端,SYN+ACK** -Google 的服务器收到 SYN,回一个包,标志位 SYN = 1, ACK = 1,自己的初始序号 `seq = y`,确认号 `ack = x + 1`(意思是"我确认收到了你的 x")。 +Google 的服务器收到 SYN,回一个包,标志位 SYN = 1, ACK = 1,自己的初始序号 `seq = y`,确认号 `ack = x + 1`(意思是"我确认收到了你的 x")。 -**第三次:客户端 → 服务器,ACK** +**第三次:客户端 → 服务器,ACK** -你的手机回最后一个包,标志位 ACK = 1,确认号 `ack = y + 1`(意思是"我确认收到了你的 y")。 +你的手机回最后一个包,标志位 ACK = 1,确认号 `ack = y + 1`(意思是"我确认收到了你的 y")。 -到这里,连接建立。注意整个过程花了一个 RTT(往返时间)——跨洋是 150ms 左右。 +到这里,连接建立。注意整个过程花了一个 RTT(往返时间)——跨洋是 150ms 左右。 ### 8.3 ISN 为什么是随机数 -初始序号(ISN)如果总是从 0 开始,攻击者就能预测、伪造连接。所以 RFC 6528 规定 ISN 要随机化,推荐的算法大致是: +初始序号(ISN)如果总是从 0 开始,攻击者就能预测、伪造连接。所以 RFC 6528 规定 ISN 要随机化,推荐的算法大致是: ``` ISN = M + F(本地IP, 本地端口, 远端IP, 远端端口, 密钥) ``` -其中 M 是一个微秒级递增的计数器(每 4 微秒加 1),F 是一个带密钥的哈希函数(比如 MD5)。这样既保证了同一个连接的 ISN 是单调递增的,又保证攻击者不知道密钥就猜不出 ISN。 +其中 M 是一个微秒级递增的计数器(每 4 微秒加 1),F 是一个带密钥的哈希函数(比如 MD5)。这样既保证了同一个连接的 ISN 是单调递增的,又保证攻击者不知道密钥就猜不出 ISN。 ### 8.4 SYN flood 攻击 -服务器收到 SYN 后,会在内存里分配一个"半连接"条目,等待客户端的 ACK。攻击者可以伪造大量源 IP 发 SYN 包但永远不发 ACK,把服务器的半连接队列塞满,正常用户就连不上了——这就是 SYN flood。 +服务器收到 SYN 后,会在内存里分配一个"半连接"条目,等待客户端的 ACK。攻击者可以伪造大量源 IP 发 SYN 包但永远不发 ACK,把服务器的半连接队列塞满,正常用户就连不上了——这就是 SYN flood。 -防御方法之一是 SYN cookie:服务器收到 SYN 时不立即分配资源,而是把连接信息编码成 ISN(用密码学方法),等收到 ACK 时再验证、分配资源。 +防御方法之一是 SYN cookie:服务器收到 SYN 时不立即分配资源,而是把连接信息编码成 ISN(用密码学方法),等收到 ACK 时再验证、分配资源。 -**这一章的物理 / 数学**:这一段从硬件抬到了"逻辑信道"层。底层数学不再是物理,而是**协议语义+概率与排队**:三次握手是分布式系统里"两军问题"的近似解(完全可靠的握手在异步网络里被证明不可能,TCP 选择"足够好");ISN 用密码学哈希 → 信息论意义上的不可预测性;SYN flood / SYN cookie → 状态机被滥用与防御。 +**这一章的物理 / 数学**:这一段从硬件抬到了"逻辑信道"层。底层数学不再是物理,而是**协议语义+概率与排队**:三次握手是分布式系统里"两军问题"的近似解(完全可靠的握手在异步网络里被证明不可能,TCP 选择"足够好");ISN 用密码学哈希 → 信息论意义上的不可预测性;SYN flood / SYN cookie → 状态机被滥用与防御。 --- -## 第 9 章 TLS 握手:让中间人看不懂 +## 第 9 章 TLS 握手:让中间人看不懂 -TCP 通了之后,还不能直接发 HTTP 请求——HTTPS 要求所有应用数据都加密。所以接下来要做 TLS 握手。 +TCP 通了之后,还不能直接发 HTTP 请求——HTTPS 要求所有应用数据都加密。所以接下来要做 TLS 握手。 ### 9.1 TLS 1.3 的握手流程 -我们以最新的 TLS 1.3 为例(它把握手压缩到 1 个 RTT,比 1.2 快一半)。 +我们以最新的 TLS 1.3 为例(它把握手压缩到 1 个 RTT,比 1.2 快一半)。 -**ClientHello**:你的手机发出第一条消息,内容包括: -- 支持的加密套件列表(比如 TLS_AES_256_GCM_SHA384) -- 一个随机数(32 字节) -- 一个临时的 ECDH 公钥(下面解释) -- SNI(Server Name Indication),告诉服务器你想访问 `www.google.com`(因为同一个 IP 可能托管多个域名) +**ClientHello**:你的手机发出第一条消息,内容包括: +- 支持的加密套件列表(比如 TLS_AES_256_GCM_SHA384) +- 一个随机数(32 字节) +- 一个临时的 ECDH 公钥(下面解释) +- SNI(Server Name Indication),告诉服务器你想访问 `www.google.com`(因为同一个 IP 可能托管多个域名) -**ServerHello + Certificate + Finished**:Google 服务器收到后,选定一个加密套件,生成自己的临时 ECDH 公钥,把它和自己的证书一起发回来。证书里包含 Google 的公钥,以及由 CA(证书颁发机构,比如 GTS)签的数字签名。 +**ServerHello + Certificate + Finished**:Google 服务器收到后,选定一个加密套件,生成自己的临时 ECDH 公钥,把它和自己的证书一起发回来。证书里包含 Google 的公钥,以及由 CA(证书颁发机构,比如 GTS)签的数字签名。 -**客户端验证证书 + 派生密钥 + Finished**:你的手机用预装的根证书验证 Google 证书的签名是真的(意味着真的是 Google 控制这个域名),然后用 ECDH 算出共享密钥,再用它派生出对称加密密钥。 +**客户端验证证书 + 派生密钥 + Finished**:你的手机用预装的根证书验证 Google 证书的签名是真的(意味着真的是 Google 控制这个域名),然后用 ECDH 算出共享密钥,再用它派生出对称加密密钥。 到这里 TLS 握手完成。后续的 HTTP 数据全部用对称密钥加密发送。 -### 9.2 ECDHE:密钥怎么"凭空"协商出来的 +### 9.2 ECDHE:密钥怎么"凭空"协商出来的 -这是整个 TLS 最神奇的部分。两个素不相识的人,在公开的信道上交换信息,中间人能看见全部交换内容,但他们俩能算出一个共享密钥而中间人算不出。 +这是整个 TLS 最神奇的部分。两个素不相识的人,在公开的信道上交换信息,中间人能看见全部交换内容,但他们俩能算出一个共享密钥而中间人算不出。 -原理是 **Diffie-Hellman 密钥交换**——1976 年由 **惠特菲尔德·迪菲(Whitfield Diffie)** 和 **马丁·赫尔曼(Martin Hellman)** 在《密码学的新方向》里提出。简化版本: +原理是 **Diffie-Hellman 密钥交换**——1976 年由 **惠特菲尔德·迪菲(Whitfield Diffie)** 和 **马丁·赫尔曼(Martin Hellman)** 在《密码学的新方向》里提出。简化版本: 1. 双方公开商定一个大素数 p 和一个生成元 g。 -2. 你的手机随机选一个秘密数 a,算 `g^a mod p`,把结果(g^a)发给服务器。 -3. 服务器随机选一个秘密数 b,算 `g^b mod p`,把结果(g^b)发给你。 +2. 你的手机随机选一个秘密数 a,算 `g^a mod p`,把结果(g^a)发给服务器。 +3. 服务器随机选一个秘密数 b,算 `g^b mod p`,把结果(g^b)发给你。 4. 你的手机算 `(g^b)^a mod p = g^(ab) mod p`。 5. 服务器算 `(g^a)^b mod p = g^(ab) mod p`。 两边算出的结果相同——这就是共享密钥。 -中间人看到的是 g、p、g^a、g^b。要算出 g^(ab),他必须从 g^a 反推出 a(或从 g^b 反推出 b)。这就是"离散对数问题":知道 g 和 g^a mod p,求 a。 +中间人看到的是 g、p、g^a、g^b。要算出 g^(ab),他必须从 g^a 反推出 a(或从 g^b 反推出 b)。这就是"离散对数问题":知道 g 和 g^a mod p,求 a。 -在 p 是 2048 位以上的大素数时,目前没有任何已知算法能在合理时间内解决**离散对数问题(DLP)**。这就是 Diffie-Hellman 的安全基础。 +在 p 是 2048 位以上的大素数时,目前没有任何已知算法能在合理时间内解决**离散对数问题(DLP)**。这就是 Diffie-Hellman 的安全基础。 -实际中 TLS 用的是椭圆曲线版本(**ECDHE**),把"模幂"换成"椭圆曲线上的点乘",数学结构更紧凑,256 位的椭圆曲线密钥相当于 3072 位的 RSA 安全强度。 +实际中 TLS 用的是椭圆曲线版本(**ECDHE**),把"模幂"换成"椭圆曲线上的点乘",数学结构更紧凑,256 位的椭圆曲线密钥相当于 3072 位的 RSA 安全强度。 -**底层的数学:为什么这玩意儿是安全的**。再多拆一层,公钥密码学这一整套魔法,根基是几条互相咬合的数学事实: +**底层的数学:为什么这玩意儿是安全的**。再多拆一层,公钥密码学这一整套魔法,根基是几条互相咬合的数学事实: -- **质数是无穷多的**(**欧几里得(Euclid)**,公元前 300 年)——所以选一个 2048 位的大质数 `p` 永远有得选。 -- **群论 / 循环群**:`{1, 2, ..., p-1}` 在模 `p` 乘法下构成一个有限循环群,生成元 `g` 能"转"出整个群。`g^a mod p` 就是在这个圆环上转 `a` 步。 -- **欧拉定理 / 费马小定理**:`g^(p-1) ≡ 1 mod p`(p 是质数时)——这是模幂运算每一步的合法性保证。**皮埃尔·德·费马(Pierre de Fermat)** 1640 年提出特例,**莱昂哈德·欧拉(Leonhard Euler)** 1763 年推广到合数。 -- **离散对数难题(DLP)**:正向算 `g^a mod p` 用快速幂只要 `O(log a)` 步,反向找 `a` 目前最好的算法是 **GNFS 数域筛**,复杂度仍是亚指数级。**正算秒级完成,反算要宇宙年龄,这条不对称性就是公钥密码的"魔法泉源"**。 -- **椭圆曲线**:把"群"从 `(整数, 模乘)` 换到"椭圆曲线上的点和切线相加"。曲线方程 `y² = x³ + ax + b (mod p)`,点之间定义一种"加法"满足群公理。点乘 `[k]P` 正向快、反向(已知 `[k]P` 求 `k`)同样指数级困难——这叫**椭圆曲线离散对数难题(ECDLP)**。优势是"群结构更紧凑",同样安全级别需要的位数小一个量级。 -- **量子计算的威胁**:**Shor 算法** 1994 年由 **彼得·肖尔(Peter Shor)** 提出,理论上量子计算机能在多项式时间内解决离散对数和大整数分解。所以 NIST 已经在推**后量子密码(PQC)**(基于格、码、多变量、哈希),TLS 1.3 已经能跑混合方案(ECDHE + Kyber)。这是一根悬在头顶的剑。 +- **质数是无穷多的**(**欧几里得(Euclid)**,公元前 300 年)——所以选一个 2048 位的大质数 `p` 永远有得选。 +- **群论 / 循环群**:`{1, 2, ..., p-1}` 在模 `p` 乘法下构成一个有限循环群,生成元 `g` 能"转"出整个群。`g^a mod p` 就是在这个圆环上转 `a` 步。 +- **欧拉定理 / 费马小定理**:`g^(p-1) ≡ 1 mod p`(p 是质数时)——这是模幂运算每一步的合法性保证。**皮埃尔·德·费马(Pierre de Fermat)** 1640 年提出特例,**莱昂哈德·欧拉(Leonhard Euler)** 1763 年推广到合数。 +- **离散对数难题(DLP)**:正向算 `g^a mod p` 用快速幂只要 `O(log a)` 步,反向找 `a` 目前最好的算法是 **GNFS 数域筛**,复杂度仍是亚指数级。**正算秒级完成,反算要宇宙年龄,这条不对称性就是公钥密码的"魔法泉源"**。 +- **椭圆曲线**:把"群"从 `(整数, 模乘)` 换到"椭圆曲线上的点和切线相加"。曲线方程 `y² = x³ + ax + b (mod p)`,点之间定义一种"加法"满足群公理。点乘 `[k]P` 正向快、反向(已知 `[k]P` 求 `k`)同样指数级困难——这叫**椭圆曲线离散对数难题(ECDLP)**。优势是"群结构更紧凑",同样安全级别需要的位数小一个量级。 +- **量子计算的威胁**:**Shor 算法** 1994 年由 **彼得·肖尔(Peter Shor)** 提出,理论上量子计算机能在多项式时间内解决离散对数和大整数分解。所以 NIST 已经在推**后量子密码(PQC)**(基于格、码、多变量、哈希),TLS 1.3 已经能跑混合方案(ECDHE + Kyber)。这是一根悬在头顶的剑。 -一句话总结:**整个 HTTPS 的"私"字,本质上压在"模幂 / 点乘"这两个数学操作的不对称性上**。 +一句话总结:**整个 HTTPS 的"私"字,本质上压在"模幂 / 点乘"这两个数学操作的不对称性上**。 -### 9.3 对称加密:AES-GCM +### 9.3 对称加密:AES-GCM -握手完成后,所有数据用 AES-GCM 加密。AES 是分组密码,把数据按 128 位分块,每块用密钥经过 10/12/14 轮(取决于密钥长度)的字节替换、行移位、列混合、轮密钥加,变成密文。 +握手完成后,所有数据用 AES-GCM 加密。AES 是分组密码,把数据按 128 位分块,每块用密钥经过 10/12/14 轮(取决于密钥长度)的字节替换、行移位、列混合、轮密钥加,变成密文。 -GCM 模式在加密之外还加了认证——不仅保证别人看不懂,还保证别人改不了内容(改了能被发现)。 +GCM 模式在加密之外还加了认证——不仅保证别人看不懂,还保证别人改不了内容(改了能被发现)。 -**AES 背后是有限域**(**Galois Field**,GF(2⁸))——这一支代数结构以 19 世纪法国早夭天才 **埃瓦里斯特·伽罗瓦(Évariste Galois)** 命名,他 20 岁因决斗去世,死前一夜赶写出来的论文奠定了群论。每一字节被当作 GF(2⁸) 上的一个元素,加法是按位异或,乘法是带模约的多项式乘法。AES 的"列混合"(MixColumns)是这个域上的矩阵乘法,"S-box"是 `x → x⁻¹` 求逆再做仿射变换,这两步专门让线性 / 差分密码分析很难奏效。说白了,AES 之所以经得住二十多年的攻击,是因为它把"扩散 / 混淆"两个目标转化成了一个高度非线性的代数对象上的操作——纸面上简单,但破译它要解一个看起来非线性、实则缺乏可利用结构的方程组。 +**AES 背后是有限域**(**Galois Field**,GF(2⁸))——这一支代数结构以 19 世纪法国早夭天才 **埃瓦里斯特·伽罗瓦(Évariste Galois)** 命名,他 20 岁因决斗去世,死前一夜赶写出来的论文奠定了群论。每一字节被当作 GF(2⁸) 上的一个元素,加法是按位异或,乘法是带模约的多项式乘法。AES 的"列混合"(MixColumns)是这个域上的矩阵乘法,"S-box"是 `x → x⁻¹` 求逆再做仿射变换,这两步专门让线性 / 差分密码分析很难奏效。说白了,AES 之所以经得住二十多年的攻击,是因为它把"扩散 / 混淆"两个目标转化成了一个高度非线性的代数对象上的操作——纸面上简单,但破译它要解一个看起来非线性、实则缺乏可利用结构的方程组。 -AES 的"麻烦"在于 S-box(字节替换表)的查表操作,软件实现速度有限。所以 Intel 自 2010 年起在 CPU 里加入了 AES-NI 指令集,把 AES 的一轮做成单条指令(`AESENC`、`AESDEC` 等),性能提升 5-10 倍。ARM 也有等价的指令(`AESE`、`AESMC`)。手机和服务器现在都用硬件 AES。 +AES 的"麻烦"在于 S-box(字节替换表)的查表操作,软件实现速度有限。所以 Intel 自 2010 年起在 CPU 里加入了 AES-NI 指令集,把 AES 的一轮做成单条指令(`AESENC`、`AESDEC` 等),性能提升 5-10 倍。ARM 也有等价的指令(`AESE`、`AESMC`)。手机和服务器现在都用硬件 AES。 -GCM 的"认证"那一半,靠的是 GHASH——又是一个 GF(2¹²⁸) 上的多项式求值。所以"AES-GCM"这五个字背后,其实压着两层有限域代数。 +GCM 的"认证"那一半,靠的是 GHASH——又是一个 GF(2¹²⁸) 上的多项式求值。所以"AES-GCM"这五个字背后,其实压着两层有限域代数。 -### 9.4 证书验签:RSA 或 ECDSA +### 9.4 证书验签:RSA 或 ECDSA -证书的签名验证是另一类密码学操作。CA 用自己的私钥对(域名 + 公钥 + 有效期 + ...)做哈希,然后签名。你的设备用 CA 的公钥验签。 +证书的签名验证是另一类密码学操作。CA 用自己的私钥对(域名 + 公钥 + 有效期 + ...)做哈希,然后签名。你的设备用 CA 的公钥验签。 -签名算法常用 **RSA-PSS**(基于**大整数分解难题**——由 **Rivest / Shamir / Adleman** 1977 年发表,所以叫 RSA)或 **ECDSA**(基于**椭圆曲线离散对数难题**)。验签涉及大量大数模幂运算,服务器侧通常有专门的硬件加速(QAT、专用加密卡)。 +签名算法常用 **RSA-PSS**(基于**大整数分解难题**——由 **Rivest / Shamir / Adleman** 1977 年发表,所以叫 RSA)或 **ECDSA**(基于**椭圆曲线离散对数难题**)。验签涉及大量大数模幂运算,服务器侧通常有专门的硬件加速(QAT、专用加密卡)。 -### 9.5 哈希函数:看不出原文,改一位就翻天 +### 9.5 哈希函数:看不出原文,改一位就翻天 -证书签名、HMAC、TLS 派生密钥、TCP SYN cookie、git commit、区块链——只要听到"摘要"二字,后面跟着的多半是哈希函数。常用的是 SHA-256 / SHA-384(SHA-2 家族)和近年标准化的 SHA-3(基于海绵结构 Keccak)。 +证书签名、HMAC、TLS 派生密钥、TCP SYN cookie、git commit、区块链——只要听到"摘要"二字,后面跟着的多半是哈希函数。常用的是 SHA-256 / SHA-384(SHA-2 家族)和近年标准化的 SHA-3(基于海绵结构 Keccak)。 -一个好的哈希函数同时满足三件事: +一个好的哈希函数同时满足三件事: -- **抗原像**:给定哈希值 `H(x)`,反推 `x` 不可行 -- **抗第二原像**:给定 `x`,找一个 `x' ≠ x` 使 `H(x) = H(x')` 不可行 -- **抗碰撞**:找任意两个不同的 `x ≠ y` 使 `H(x) = H(y)` 不可行 +- **抗原像**:给定哈希值 `H(x)`,反推 `x` 不可行 +- **抗第二原像**:给定 `x`,找一个 `x' ≠ x` 使 `H(x) = H(x')` 不可行 +- **抗碰撞**:找任意两个不同的 `x ≠ y` 使 `H(x) = H(y)` 不可行 -外加一个直观但关键的性质——**雪崩效应**:输入改一比特,输出大概有一半比特会翻。这就是为什么改一个空格 git commit 哈希就完全变样。 +外加一个直观但关键的性质——**雪崩效应**:输入改一比特,输出大概有一半比特会翻。这就是为什么改一个空格 git commit 哈希就完全变样。 -底层数学不像 RSA / ECC 那样压在某个"难题"上,更像是一种"足够混乱以至于看起来随机"的工程构造——SHA-2 用一堆"加 / 异或 / 移位 / 模加"反复迭代,SHA-3 用海绵结构吸 / 挤数据。安全性靠的是几十年没人能找到捷径,不是数学定理保证的(这一点和 RSA / ECC 不同)。 +底层数学不像 RSA / ECC 那样压在某个"难题"上,更像是一种"足够混乱以至于看起来随机"的工程构造——SHA-2 用一堆"加 / 异或 / 移位 / 模加"反复迭代,SHA-3 用海绵结构吸 / 挤数据。安全性靠的是几十年没人能找到捷径,不是数学定理保证的(这一点和 RSA / ECC 不同)。 -**这一章的物理 / 数学(整章总结)**:数论(质数、模幂、欧拉定理)→ DH / RSA;群论 + 椭圆曲线代数 → ECDHE / ECDSA;有限域 GF(2⁸) / GF(2¹²⁸) → AES + GHASH;计算复杂性(单向函数 + 难题假设)→ 整个公钥密码的安全感;雪崩效应 + 抗碰撞 → 哈希函数。这一整层是"用数学算出别人算不出来的东西",是 HTTPS 之所以叫 HTTPS 的全部原因。 +**这一章的物理 / 数学(整章总结)**:数论(质数、模幂、欧拉定理)→ DH / RSA;群论 + 椭圆曲线代数 → ECDHE / ECDSA;有限域 GF(2⁸) / GF(2¹²⁸) → AES + GHASH;计算复杂性(单向函数 + 难题假设)→ 整个公钥密码的安全感;雪崩效应 + 抗碰撞 → 哈希函数。这一整层是"用数学算出别人算不出来的东西",是 HTTPS 之所以叫 HTTPS 的全部原因。 -### 9.6 HTTPS = HTTP + TLS:把零件拼起来 +### 9.6 HTTPS = HTTP + TLS:把零件拼起来 -到这一章结束,你已经把 HTTPS 的所有零件全部走了一遍——是时候把它们拼起来,看清楚 HTTPS 到底长什么样。 +到这一章结束,你已经把 HTTPS 的所有零件全部走了一遍——是时候把它们拼起来,看清楚 HTTPS 到底长什么样。 **HTTPS 的"洋葱"结构** -回想一下 [§0.1](#01-顺手把-https-拆成它的零件) 那张表,每一层在哪一章讲过、干什么: +回想一下 [§0.1](#01-顺手把-https-拆成它的零件) 那张表,每一层在哪一章讲过、干什么: | 层 | 协议 | 作用 | 在哪讲 | |---|---|---|---| @@ -746,7 +746,7 @@ GCM 的"认证"那一半,靠的是 GHASH——又是一个 GF(2¹²⁸) 上的 | 网络层 | **IP** | 路由、寻址 | 第 5 章 | | 物理层 | 无线 / 光纤 | 真正把比特送出去 | 第 1-3 章、第 7 章 | -**真正发出去的字节是这样套娃的:** +**真正发出去的字节是这样套娃的:** ``` 你想发的 HTTP 请求(明文,只有你和 Google 看): @@ -774,30 +774,30 @@ IP Packet: 电磁波 / 光子在物理介质里飞 ``` -**关键观察**:**每一层只看自己的头**。路由器只看 IP 头(它根本不知道里面是 TCP 还是 UDP);TCP 协议栈只看 TCP 头(它不知道里面是不是 TLS 加密内容);TLS 库只解密 TLS 内容(它不关心里面是 HTTP 还是 SMTP);浏览器只看 HTTP(它不操心下面有没有加密)。这种**严格的分层 + 接口稳定**,是互联网能让几十种技术互不干扰拼在一起的根本原因。 +**关键观察**:**每一层只看自己的头**。路由器只看 IP 头(它根本不知道里面是 TCP 还是 UDP);TCP 协议栈只看 TCP 头(它不知道里面是不是 TLS 加密内容);TLS 库只解密 TLS 内容(它不关心里面是 HTTP 还是 SMTP);浏览器只看 HTTP(它不操心下面有没有加密)。这种**严格的分层 + 接口稳定**,是互联网能让几十种技术互不干扰拼在一起的根本原因。 -**接收端反向拆"洋葱"**:物理层把帧还原成 IP 包,IP 层把 TCP 段交给 TCP 协议栈,TCP 层重组出 TLS 加密字节流,TLS 层用握手协商出来的密钥解密出 HTTP 明文,HTTP 层把请求交给应用——也就是 Google 搜索服务。 +**接收端反向拆"洋葱"**:物理层把帧还原成 IP 包,IP 层把 TCP 段交给 TCP 协议栈,TCP 层重组出 TLS 加密字节流,TLS 层用握手协商出来的密钥解密出 HTTP 明文,HTTP 层把请求交给应用——也就是 Google 搜索服务。 **HTTPS 里的"S"到底加了什么** -| 没有 S 的 HTTP(80 端口) | 加了 S 的 HTTPS(443 端口) | +| 没有 S 的 HTTP(80 端口) | 加了 S 的 HTTPS(443 端口) | |---|---| -| 中间人能**看**到所有内容(URL、headers、body) | 中间人**看不到**内容,只看到加密字节流 | -| 中间人能**改**内容(注入广告、篡改下载) | 中间人**改不了**(GCM 认证位会失败) | -| 你不知道**对面真的是 Google** | 你**确认**对面是 Google(证书验签) | -| 任意 ISP 都能做"中间人攻击" | 中间人攻击需要伪造证书,正常情况下不可能 | +| 中间人能**看**到所有内容(URL、headers、body) | 中间人**看不到**内容,只看到加密字节流 | +| 中间人能**改**内容(注入广告、篡改下载) | 中间人**改不了**(GCM 认证位会失败) | +| 你不知道**对面真的是 Google** | 你**确认**对面是 Google(证书验签) | +| 任意 ISP 都能做"中间人攻击" | 中间人攻击需要伪造证书,正常情况下不可能 | -第三条尤其关键:**HTTPS 不只是加密,还做身份验证**。光加密不验证,你可能加密地连到一个伪装成 Google 的钓鱼网站;光验证不加密,内容会被偷看。两者必须同时有。这两件事都靠这一章讲的密码学:**ECDHE 协商密钥**(防偷看)+ **证书验签 / RSA 或 ECDSA**(防冒充)+ **AES-GCM**(加密 + 防篡改一体)+ **哈希**(把"完整性"压缩成 32 字节摘要)。 +第三条尤其关键:**HTTPS 不只是加密,还做身份验证**。光加密不验证,你可能加密地连到一个伪装成 Google 的钓鱼网站;光验证不加密,内容会被偷看。两者必须同时有。这两件事都靠这一章讲的密码学:**ECDHE 协商密钥**(防偷看)+ **证书验签 / RSA 或 ECDSA**(防冒充)+ **AES-GCM**(加密 + 防篡改一体)+ **哈希**(把"完整性"压缩成 32 字节摘要)。 -**所以,HTTPS 这三个字到底是什么** +**所以,HTTPS 这三个字到底是什么** -一句话:**HTTP 这个最普通的请求-响应协议,被装进 TLS 这条加密+验证身份的暗管里,这条暗管又架在 TCP 这条可靠通道上**。 +一句话:**HTTP 这个最普通的请求-响应协议,被装进 TLS 这条加密+验证身份的暗管里,这条暗管又架在 TCP 这条可靠通道上**。 -更短的一句话:**HTTPS 就是"在不可信的互联网上,装出一条可信的通道"**。 +更短的一句话:**HTTPS 就是"在不可信的互联网上,装出一条可信的通道"**。 -而这条"可信通道",其实是用前面整篇文档的全部内容堆出来的——物理层把比特送到位、TCP 让字节流不乱、TLS 让内容看不见也改不了、HTTP 让两边知道在聊什么、CA 体系让你确信对面是真 Google、GFW 试图把这条通道掐掉、Reality 又试图让这条通道看起来像别人的通道。 +而这条"可信通道",其实是用前面整篇文档的全部内容堆出来的——物理层把比特送到位、TCP 让字节流不乱、TLS 让内容看不见也改不了、HTTP 让两边知道在聊什么、CA 体系让你确信对面是真 Google、GFW 试图把这条通道掐掉、Reality 又试图让这条通道看起来像别人的通道。 -下一章开始,我们看 Google 的服务器在另一端是怎么把这个洋葱一层层剥开的。 +下一章开始,我们看 Google 的服务器在另一端是怎么把这个洋葱一层层剥开的。 --- @@ -805,30 +805,30 @@ IP Packet: ### 10.1 Google 的网络入口 -你的加密数据包到达 Google 的某个数据中心入口。Google 全球有几十个数据中心,加上几百个边缘节点(POP)。请求会被引导到离你最近、负载较轻的一个。 +你的加密数据包到达 Google 的某个数据中心入口。Google 全球有几十个数据中心,加上几百个边缘节点(POP)。请求会被引导到离你最近、负载较轻的一个。 -入口处会经过: +入口处会经过: -**边缘路由器**:跑 BGP 协议,和外部互联网互联。 -**DDoS 清洗**:Google 自研的 DDoS 防护系统(以及部分外部商用方案),识别和过滤恶意流量。 -**Maglev 负载均衡**:Google 自研的软件负载均衡器,运行在普通 Linux 服务器上,用一致性哈希把请求分配给后端服务器集群。 +**边缘路由器**:跑 BGP 协议,和外部互联网互联。 +**DDoS 清洗**:Google 自研的 DDoS 防护系统(以及部分外部商用方案),识别和过滤恶意流量。 +**Maglev 负载均衡**:Google 自研的软件负载均衡器,运行在普通 Linux 服务器上,用一致性哈希把请求分配给后端服务器集群。 ### 10.2 一致性哈希 -负载均衡器要决定:这个请求该发给哪台后端服务器?如果用简单的"哈希取模",一旦后端服务器数量变化(扩容、缩容、宕机),大量连接会被重新分配,影响用户体验。 +负载均衡器要决定:这个请求该发给哪台后端服务器?如果用简单的"哈希取模",一旦后端服务器数量变化(扩容、缩容、宕机),大量连接会被重新分配,影响用户体验。 -**一致性哈希(Consistent Hashing)** 的思路是把所有后端服务器和所有请求都映射到一个圆环上(用哈希函数),每个请求顺时针找到的第一台服务器就是它的归属。这样添加或删除一台服务器,只影响圆环上相邻的一段,绝大多数连接不受影响。这套算法 1997 年由 **David Karger 等人** 在 MIT 提出,后来在 Cassandra、DynamoDB、CDN、Maglev 里反复出现。 +**一致性哈希(Consistent Hashing)** 的思路是把所有后端服务器和所有请求都映射到一个圆环上(用哈希函数),每个请求顺时针找到的第一台服务器就是它的归属。这样添加或删除一台服务器,只影响圆环上相邻的一段,绝大多数连接不受影响。这套算法 1997 年由 **David Karger 等人** 在 MIT 提出,后来在 Cassandra、DynamoDB、CDN、Maglev 里反复出现。 -Google Maglev 用的是改进版"Maglev hashing",在保持一致性的同时让负载更均衡。 +Google Maglev 用的是改进版"Maglev hashing",在保持一致性的同时让负载更均衡。 ### 10.3 TOR 交换机和 Spine-Leaf 架构 -数据中心内部的网络架构是 Spine-Leaf: +数据中心内部的网络架构是 Spine-Leaf: -- **Leaf 交换机**(也叫 TOR,Top of Rack):每个机柜顶部一台,连接机柜内所有服务器。 -- **Spine 交换机**:每台 Leaf 交换机都和所有 Spine 交换机相连,形成一个全连接的两层结构。 +- **Leaf 交换机**(也叫 TOR,Top of Rack):每个机柜顶部一台,连接机柜内所有服务器。 +- **Spine 交换机**:每台 Leaf 交换机都和所有 Spine 交换机相连,形成一个全连接的两层结构。 -这种架构的好处是任意两台服务器之间最多两跳,延迟和带宽可预测。Google 自研的数据中心交换机(代号 Jupiter)用商用的转发 ASIC(博通 Tomahawk 或类似芯片)做线速转发,集群带宽可以达到 PB 级。 +这种架构的好处是任意两台服务器之间最多两跳,延迟和带宽可预测。Google 自研的数据中心交换机(代号 Jupiter)用商用的转发 ASIC(博通 Tomahawk 或类似芯片)做线速转发,集群带宽可以达到 PB 级。 --- @@ -836,42 +836,42 @@ Google Maglev 用的是改进版"Maglev hashing",在保持一致性的同时让 ### 11.1 网卡到 CPU -你的数据包终于到达 Google 一台具体的服务器。服务器的网卡(可能是 NVIDIA Mellanox ConnectX-6 或 Google 自研的)收到光信号,光模块转换成电信号,网卡的 MAC 控制器解析以太网头,做以下处理: +你的数据包终于到达 Google 一台具体的服务器。服务器的网卡(可能是 NVIDIA Mellanox ConnectX-6 或 Google 自研的)收到光信号,光模块转换成电信号,网卡的 MAC 控制器解析以太网头,做以下处理: -**校验和卸载**:网卡硬件验证 IP 和 TCP 校验和,正确才往上交。 -**RSS(接收侧扩展)**:网卡根据数据包的四元组(源IP、源端口、目的IP、目的端口)做哈希,把不同的连接分配到不同的 CPU 核心,避免单核成为瓶颈。 -**DMA 写内存**:网卡通过 PCIe 总线,用 DMA 把数据包直接写到指定的内存区域,完全不打扰 CPU。 -**触发中断**:写完后,网卡给对应的 CPU 核心发一个 MSI-X 中断,告诉它"有新数据了"。 +**校验和卸载**:网卡硬件验证 IP 和 TCP 校验和,正确才往上交。 +**RSS(接收侧扩展)**:网卡根据数据包的四元组(源IP、源端口、目的IP、目的端口)做哈希,把不同的连接分配到不同的 CPU 核心,避免单核成为瓶颈。 +**DMA 写内存**:网卡通过 PCIe 总线,用 DMA 把数据包直接写到指定的内存区域,完全不打扰 CPU。 +**触发中断**:写完后,网卡给对应的 CPU 核心发一个 MSI-X 中断,告诉它"有新数据了"。 ### 11.2 内核协议栈 -CPU 收到中断,进入中断处理程序。Linux 内核的网络协议栈处理顺序大致是: +CPU 收到中断,进入中断处理程序。Linux 内核的网络协议栈处理顺序大致是: -1. **硬中断处理**:网卡驱动响应中断,把这个数据包"挂"到该 CPU 的待处理队列上,然后立即返回(尽快释放硬中断)。 -2. **软中断处理(NAPI)**:稍后,内核的 ksoftirqd 线程批量处理待处理队列,一次拉一批包(典型 64 个),减少中断开销。 -3. **IP 层**:检查 IP 头,如果是分片包则重组。 -4. **TCP 层**:根据四元组找到对应的 socket,把数据按序号放入 socket 接收缓冲区。如果序号有跳跃,就缓存等后续。 -5. **唤醒应用**:如果有进程在 epoll 里等这个 socket,内核唤醒它。 +1. **硬中断处理**:网卡驱动响应中断,把这个数据包"挂"到该 CPU 的待处理队列上,然后立即返回(尽快释放硬中断)。 +2. **软中断处理(NAPI)**:稍后,内核的 ksoftirqd 线程批量处理待处理队列,一次拉一批包(典型 64 个),减少中断开销。 +3. **IP 层**:检查 IP 头,如果是分片包则重组。 +4. **TCP 层**:根据四元组找到对应的 socket,把数据按序号放入 socket 接收缓冲区。如果序号有跳跃,就缓存等后续。 +5. **唤醒应用**:如果有进程在 epoll 里等这个 socket,内核唤醒它。 -### 11.3 高性能场景:DPDK 和内核旁路 +### 11.3 高性能场景:DPDK 和内核旁路 -对于 Google 这种规模,内核协议栈的开销都嫌大。所以高性能服务用 DPDK(数据平面开发工具包)或 XDP(eXpress Data Path)做"内核旁路",让用户态程序直接和网卡打交道,避开内核拷贝和上下文切换。 +对于 Google 这种规模,内核协议栈的开销都嫌大。所以高性能服务用 DPDK(数据平面开发工具包)或 XDP(eXpress Data Path)做"内核旁路",让用户态程序直接和网卡打交道,避开内核拷贝和上下文切换。 -更激进的还有 RDMA(远程直接内存访问),让一台服务器的网卡直接读写另一台服务器的内存,完全不经过 CPU。 +更激进的还有 RDMA(远程直接内存访问),让一台服务器的网卡直接读写另一台服务器的内存,完全不经过 CPU。 -### 11.4 应用层:Google 的搜索服务 +### 11.4 应用层:Google 的搜索服务 -数据包最终到达运行在这台服务器上的某个进程,可能是 Google Front End(GFE)。GFE 解密 TLS,解析 HTTP 请求,看到 `/search?q=weather`,把它转发给后端的搜索集群。 +数据包最终到达运行在这台服务器上的某个进程,可能是 Google Front End(GFE)。GFE 解密 TLS,解析 HTTP 请求,看到 `/search?q=weather`,把它转发给后端的搜索集群。 -搜索集群是一个非常复杂的分布式系统:倒排索引、查询理解、排序、广告系统、知识图谱、个性化、垂直搜索(天气模块)等等。这些处理在几十毫秒内完成,生成 HTML 响应。 +搜索集群是一个非常复杂的分布式系统:倒排索引、查询理解、排序、广告系统、知识图谱、个性化、垂直搜索(天气模块)等等。这些处理在几十毫秒内完成,生成 HTML 响应。 -天气查询比较特殊——Google 检测到你查的是天气,会调用专门的天气模块,根据你的 IP 估算位置(或者用浏览器报的地理位置),从天气数据提供方(比如 weather.com)获取数据,渲染成搜索结果顶部的天气卡片。 +天气查询比较特殊——Google 检测到你查的是天气,会调用专门的天气模块,根据你的 IP 估算位置(或者用浏览器报的地理位置),从天气数据提供方(比如 weather.com)获取数据,渲染成搜索结果顶部的天气卡片。 -响应数据回到 GFE,被压缩(gzip 或 brotli),用 TLS 加密,封装成 TCP 包,发回网卡。 +响应数据回到 GFE,被压缩(gzip 或 brotli),用 TLS 加密,封装成 TCP 包,发回网卡。 -### 11.5 顺便补一层:服务器内部的"内存层级" +### 11.5 顺便补一层:服务器内部的"内存层级" -服务器收包之后,数据要在不同存储层之间跑一遍,这一段决定了"为什么能这么快": +服务器收包之后,数据要在不同存储层之间跑一遍,这一段决定了"为什么能这么快": ``` 寄存器(<1ns,KB 级) @@ -883,11 +883,11 @@ CPU 收到中断,进入中断处理程序。Linux 内核的网络协议栈处理 ← 网络存储(~ms,几 PB) ``` -每往下一层,延迟差一到三个数量级。CPU 之所以"快",80% 的功劳是 cache 命中得好,而不是核心频率高。处理你这一个 HTTPS 请求的时候,数据从网卡 DMA 落到 DRAM,再被 CPU "拉"到 L3 → L2 → L1 → 寄存器,一路上都靠 cache line 预取、分支预测在掩盖延迟。 +每往下一层,延迟差一到三个数量级。CPU 之所以"快",80% 的功劳是 cache 命中得好,而不是核心频率高。处理你这一个 HTTPS 请求的时候,数据从网卡 DMA 落到 DRAM,再被 CPU "拉"到 L3 → L2 → L1 → 寄存器,一路上都靠 cache line 预取、分支预测在掩盖延迟。 -这一层的"数学"是排队论 + 概率:cache 命中率本质是一个时间局部性 / 空间局部性的概率分布问题。 +这一层的"数学"是排队论 + 概率:cache 命中率本质是一个时间局部性 / 空间局部性的概率分布问题。 -**这一章的物理 / 数学**:总线 / DMA(本质是异步生产者-消费者)→ 网卡到内存零拷贝;一致性哈希(把节点摆到圆环上)→ 负载均衡的"最少扰动"性质;排队论(Little's Law: `L = λ × W`)→ 延迟 / 吞吐 / 队长的硬约束;Spine-Leaf 拓扑 → 图论上的 Clos 网络,任意两点最多两跳。 +**这一章的物理 / 数学**:总线 / DMA(本质是异步生产者-消费者)→ 网卡到内存零拷贝;一致性哈希(把节点摆到圆环上)→ 负载均衡的"最少扰动"性质;排队论(Little's Law: `L = λ × W`)→ 延迟 / 吞吐 / 队长的硬约束;Spine-Leaf 拓扑 → 图论上的 Clos 网络,任意两点最多两跳。 --- @@ -895,82 +895,82 @@ CPU 收到中断,进入中断处理程序。Linux 内核的网络协议栈处理 ### 12.1 各层都在干补救的事 -这条几千公里的旅程上,数据出错或丢失是常态。各层都有自己的补救机制: +这条几千公里的旅程上,数据出错或丢失是常态。各层都有自己的补救机制: -**物理层**:用前向纠错码(FEC)。光纤用 Reed-Solomon、SD-FEC,5G 用 LDPC、Polar。原理是加冗余位,接收端通过代数运算修正错误。 -**数据链路层**:用 CRC 检错(发现错就丢),或在 WiFi/5G 里用 ARQ 重传(链路层重传比传输层更快)。 -**传输层**:TCP 用序号 + 确认 + 超时重传 + 快速重传。 -**应用层**:QUIC 在每个流上独立重传;实时音视频用 FEC + NACK 混合。 +**物理层**:用前向纠错码(FEC)。光纤用 Reed-Solomon、SD-FEC,5G 用 LDPC、Polar。原理是加冗余位,接收端通过代数运算修正错误。 +**数据链路层**:用 CRC 检错(发现错就丢),或在 WiFi/5G 里用 ARQ 重传(链路层重传比传输层更快)。 +**传输层**:TCP 用序号 + 确认 + 超时重传 + 快速重传。 +**应用层**:QUIC 在每个流上独立重传;实时音视频用 FEC + NACK 混合。 -### 12.2 TCP 拥塞控制:不是丢包不报警,而是别让网络堵车 +### 12.2 TCP 拥塞控制:不是丢包不报警,而是别让网络堵车 -TCP 不光要可靠,还要"友好"——不能一个连接占满整条带宽。所以有拥塞控制算法。 +TCP 不光要可靠,还要"友好"——不能一个连接占满整条带宽。所以有拥塞控制算法。 -**TCP Reno**(经典):慢启动时拥塞窗口指数增长,达到阈值后线性增长;一旦丢包,窗口减半,从头慢慢涨。 +**TCP Reno**(经典):慢启动时拥塞窗口指数增长,达到阈值后线性增长;一旦丢包,窗口减半,从头慢慢涨。 -**TCP CUBIC**(Linux 默认):窗口按三次曲线变化,先快后慢再快,适合高带宽场景。 +**TCP CUBIC**(Linux 默认):窗口按三次曲线变化,先快后慢再快,适合高带宽场景。 -**TCP BBR**(Google 推出,2016 年):颠覆传统思路,不以丢包为信号,而是主动测量**带宽**和 **RTT**,直接控制发送速率匹配链路实际带宽。 +**TCP BBR**(Google 推出,2016 年):颠覆传统思路,不以丢包为信号,而是主动测量**带宽**和 **RTT**,直接控制发送速率匹配链路实际带宽。 -BBR 的核心思想是估计: +BBR 的核心思想是估计: ``` BDP = 带宽 × RTT ``` -BDP 叫**带宽延迟乘积(Bandwidth-Delay Product)**,是链路在途数据的最大量。BBR 让在途数据保持在 BDP 附近,既不浪费带宽,又不在路由器队列里堆积。 +BDP 叫**带宽延迟乘积(Bandwidth-Delay Product)**,是链路在途数据的最大量。BBR 让在途数据保持在 BDP 附近,既不浪费带宽,又不在路由器队列里堆积。 -YouTube、Google 搜索都用 BBR,显著降低了延迟和重传率。 +YouTube、Google 搜索都用 BBR,显著降低了延迟和重传率。 ### 12.3 SACK 选择性确认 -经典 TCP 的累积确认有个问题:如果你发了 1-10 号包,丢了 5 号,接收方只能确认到 4 号。发送方不知道 6-10 是不是也丢了,可能要重传 5-10 全部。 +经典 TCP 的累积确认有个问题:如果你发了 1-10 号包,丢了 5 号,接收方只能确认到 4 号。发送方不知道 6-10 是不是也丢了,可能要重传 5-10 全部。 -SACK(选择性确认)允许接收方说"我收到了 1-4 和 6-10,只缺 5"。发送方就只重传 5,效率高得多。现代 TCP 默认开启 SACK。 +SACK(选择性确认)允许接收方说"我收到了 1-4 和 6-10,只缺 5"。发送方就只重传 5,效率高得多。现代 TCP 默认开启 SACK。 ### 12.4 5G HARQ -物理层的 HARQ(混合自动重传)前面提过——简单说就是"重传不是简单重发,而是发不同的冗余信息,接收端把多次接收的数据合并解码"。这样即使每次都有错误,合并后也能正确解码。这是物理层的智慧。 +物理层的 HARQ(混合自动重传)前面提过——简单说就是"重传不是简单重发,而是发不同的冗余信息,接收端把多次接收的数据合并解码"。这样即使每次都有错误,合并后也能正确解码。这是物理层的智慧。 -**这一章的物理 / 数学**:整层都是"在不可靠的物理世界上模拟一个可靠通道"。底层是**信息论**(香农 1948)——只要信道容量大于信息率,就存在一种编码让错误率任意低;实现路径分两条:**前向纠错**(代数构造冗余,数学上是有限域 / 多项式 / 稀疏图)和**反馈重传**(利用反向链路通知重发,数学上是状态机 + 概率重试)。**TCP 拥塞控制**则是把"网络拥堵"建模成排队系统,每代算法(Reno / CUBIC / BBR)都是对"在途量 vs 实际带宽 / 排队延迟"这个动力系统的不同控制策略。 +**这一章的物理 / 数学**:整层都是"在不可靠的物理世界上模拟一个可靠通道"。底层是**信息论**(香农 1948)——只要信道容量大于信息率,就存在一种编码让错误率任意低;实现路径分两条:**前向纠错**(代数构造冗余,数学上是有限域 / 多项式 / 稀疏图)和**反馈重传**(利用反向链路通知重发,数学上是状态机 + 概率重试)。**TCP 拥塞控制**则是把"网络拥堵"建模成排队系统,每代算法(Reno / CUBIC / BBR)都是对"在途量 vs 实际带宽 / 排队延迟"这个动力系统的不同控制策略。 --- ## 第 13 章 硬件加速汇总 -整条链路上,各种"加速硬件"在默默干活。汇总一下: +整条链路上,各种"加速硬件"在默默干活。汇总一下: -**手机里**: -- 基带芯片(高通 X75)的 LDPC/Polar 解码电路、FFT 引擎 -- 主 SoC 的 AES、SHA 硬件加速指令(ARMv8 Crypto Extensions) +**手机里**: +- 基带芯片(高通 X75)的 LDPC/Polar 解码电路、FFT 引擎 +- 主 SoC 的 AES、SHA 硬件加速指令(ARMv8 Crypto Extensions) - 射频前端的 PA、SAW/BAW 滤波器 -**基站里**: +**基站里**: - BBU 的 FPGA / 专用加速卡处理 OFDM、MIMO、信道编码 - AAU 里的 64 通道收发器和数字波束成形 -**路由器里**: -- 转发 ASIC(博通 Tomahawk、思科 Silicon One) +**路由器里**: +- 转发 ASIC(博通 Tomahawk、思科 Silicon One) - TCAM 高速查找表 -- 高速串行接口(SerDes)做端口间数据传输 +- 高速串行接口(SerDes)做端口间数据传输 -**光通信里**: +**光通信里**: - EDFA 光放大器 -- 相干光收发器(集成 DSP 做色散补偿、极化解复用) +- 相干光收发器(集成 DSP 做色散补偿、极化解复用) - DWDM 复用器 -**服务器里**: +**服务器里**: - 网卡的校验和卸载、TSO/LRO、RSS、TLS 卸载 -- CPU 的 AES-NI、SHA-NI、AVX-512(用于密码学和数据处理) -- DPU 智能网卡(NVIDIA BlueField、AWS Nitro)接管网络、存储、加密任务 +- CPU 的 AES-NI、SHA-NI、AVX-512(用于密码学和数据处理) +- DPU 智能网卡(NVIDIA BlueField、AWS Nitro)接管网络、存储、加密任务 -如果没有这些专用硬件,所有事情都靠 CPU 软件实现,整个互联网的吞吐量大概只能达到现在的 1%——而且功耗会爆炸。 +如果没有这些专用硬件,所有事情都靠 CPU 软件实现,整个互联网的吞吐量大概只能达到现在的 1%——而且功耗会爆炸。 --- -## 第 14 章 返回:数据包的回家路 +## 第 14 章 返回:数据包的回家路 -Google 服务器生成的响应数据,要走和来时差不多的路径回到你的手机: +Google 服务器生成的响应数据,要走和来时差不多的路径回到你的手机: ``` 应用进程 → 内核协议栈 → 网卡 → TOR → Spine @@ -981,64 +981,64 @@ Google 服务器生成的响应数据,要走和来时差不多的路径回到你 → JavaScript 引擎 → 排版 → GPU 合成 → 屏幕显示 ``` -下行链路上,基站到手机方向也是用 OFDM、Massive MIMO、LDPC,但参数和上行略有不同(下行通常用更高的调制阶数,因为基站发射功率大)。 +下行链路上,基站到手机方向也是用 OFDM、Massive MIMO、LDPC,但参数和上行略有不同(下行通常用更高的调制阶数,因为基站发射功率大)。 -手机收到 HTTP 响应后,Chrome 解密 TLS,解压 gzip/brotli,把 HTML 交给渲染引擎(Blink),解析 DOM 树,执行 JavaScript,布局,光栅化,合成,最后通过 GPU 把像素送到屏幕。 +手机收到 HTTP 响应后,Chrome 解密 TLS,解压 gzip/brotli,把 HTML 交给渲染引擎(Blink),解析 DOM 树,执行 JavaScript,布局,光栅化,合成,最后通过 GPU 把像素送到屏幕。 -屏幕的 **OLED** 像素接到驱动信号,每个红绿蓝子像素发出对应亮度的光——这一步又是量子物理:OLED 是有机半导体,电子和空穴在有机层里复合释放光子。你看到了天气预报。 +屏幕的 **OLED** 像素接到驱动信号,每个红绿蓝子像素发出对应亮度的光——这一步又是量子物理:OLED 是有机半导体,电子和空穴在有机层里复合释放光子。你看到了天气预报。 -整个过程从你点击到看到结果,如果一切顺利,大概 300-800 毫秒。 +整个过程从你点击到看到结果,如果一切顺利,大概 300-800 毫秒。 --- ## 附录 A 关键公式速查 -> 不必逐条记。这张表的用法是:碰到链路里某一步,知道"是哪条公式 / 哪条定律在起作用"就够了。 +> 不必逐条记。这张表的用法是:碰到链路里某一步,知道"是哪条公式 / 哪条定律在起作用"就够了。 -### 物理层(电磁、光、半导体) +### 物理层(电磁、光、半导体) | 名称 | 公式 | 在哪一章用上 | |------|------|------| -| **Maxwell 方程组** | ∇·E=ρ/ε₀, ∇·B=0, ∇×E=−∂B/∂t, ∇×B=μ₀J+μ₀ε₀∂E/∂t | 一切电磁波的存在与传播(Ch3, Ch5, Ch7) | -| **光速 / 频率 / 波长** | c = λ × f | 决定天线尺寸、频段选用(Ch3) | -| **Friis 自由空间路径损耗** | P_r = P_t × G_t × G_r × (λ/4πr)² | 基站规划密度(Ch3) | -| **平板电容** | C = ε × A / d | 电容触摸屏识别(Ch1) | -| **斯涅尔定律 / 临界角** | n₁ sin θ₁ = n₂ sin θ₂; θ_c = arcsin(n₂/n₁) | 光纤全反射(Ch5) | -| **光子能量** | E = h × f | 光通信的量子尺度极限(Ch5, Ch7) | -| **受激辐射(爱因斯坦,1917)** | 入射光子诱导高能级粒子放出同模光子 | EDFA 全光放大(Ch5, Ch7) | +| **Maxwell 方程组** | ∇·E=ρ/ε₀, ∇·B=0, ∇×E=−∂B/∂t, ∇×B=μ₀J+μ₀ε₀∂E/∂t | 一切电磁波的存在与传播(Ch3, Ch5, Ch7) | +| **光速 / 频率 / 波长** | c = λ × f | 决定天线尺寸、频段选用(Ch3) | +| **Friis 自由空间路径损耗** | P_r = P_t × G_t × G_r × (λ/4πr)² | 基站规划密度(Ch3) | +| **平板电容** | C = ε × A / d | 电容触摸屏识别(Ch1) | +| **斯涅尔定律 / 临界角** | n₁ sin θ₁ = n₂ sin θ₂; θ_c = arcsin(n₂/n₁) | 光纤全反射(Ch5) | +| **光子能量** | E = h × f | 光通信的量子尺度极限(Ch5, Ch7) | +| **受激辐射(爱因斯坦,1917)** | 入射光子诱导高能级粒子放出同模光子 | EDFA 全光放大(Ch5, Ch7) | ### 信号处理 / 通信 | 名称 | 公式 | 在哪一章用上 | |------|------|------| -| **香农信道容量** | C = B × log₂(1 + SNR) | 信道理论上限(Ch3, Ch12) | -| **OFDM 信号** | s(t) = Σ Xₖ × exp(j2πkΔf·t) | 多子载波时域合成(Ch3) | -| **MIMO 信道模型** | y = H W s + n | 波束赋形 / 多天线(Ch3, Ch4) | -| **波束加权(MRC / ZF / MMSE)** | W = H^H, (H^H H)⁻¹ H^H, ... | Massive MIMO 加权矩阵选择(Ch4) | -| **CRC 校验** | 数据多项式 mod 生成多项式 | 错误检测(Ch3, Ch11) | +| **香农信道容量** | C = B × log₂(1 + SNR) | 信道理论上限(Ch3, Ch12) | +| **OFDM 信号** | s(t) = Σ Xₖ × exp(j2πkΔf·t) | 多子载波时域合成(Ch3) | +| **MIMO 信道模型** | y = H W s + n | 波束赋形 / 多天线(Ch3, Ch4) | +| **波束加权(MRC / ZF / MMSE)** | W = H^H, (H^H H)⁻¹ H^H, ... | Massive MIMO 加权矩阵选择(Ch4) | +| **CRC 校验** | 数据多项式 mod 生成多项式 | 错误检测(Ch3, Ch11) | -### 密码学(数论 / 群论 / 有限域) +### 密码学(数论 / 群论 / 有限域) | 名称 | 公式 / 概念 | 在哪一章用上 | |------|------|------| -| **欧拉 / 费马小定理** | g^(p−1) ≡ 1 (mod p),p 为质数 | 模幂运算的代数基础(Ch9) | -| **Diffie-Hellman 共享密钥** | K = g^(ab) mod p | 双方公开协商出共同密钥(Ch9) | -| **离散对数难题(DLP / ECDLP)** | 已知 g, g^a 求 a;椭圆曲线上同理 | 公钥密码安全的根(Ch9) | +| **欧拉 / 费马小定理** | g^(p−1) ≡ 1 (mod p),p 为质数 | 模幂运算的代数基础(Ch9) | +| **Diffie-Hellman 共享密钥** | K = g^(ab) mod p | 双方公开协商出共同密钥(Ch9) | +| **离散对数难题(DLP / ECDLP)** | 已知 g, g^a 求 a;椭圆曲线上同理 | 公钥密码安全的根(Ch9) | | **椭圆曲线** | y² = x³ + ax + b (mod p) | ECDHE / ECDSA(Ch9) | -| **AES 一轮** | SubBytes → ShiftRows → MixColumns → AddRoundKey | 对称加密的基本单元(Ch9) | -| **AES 的有限域** | GF(2⁸) 上的多项式运算 | S-box 求逆、列混合(Ch9) | -| **GHASH(GCM 认证)** | GF(2¹²⁸) 上多项式求值 | AES-GCM 的认证位(Ch9) | +| **AES 一轮** | SubBytes → ShiftRows → MixColumns → AddRoundKey | 对称加密的基本单元(Ch9) | +| **AES 的有限域** | GF(2⁸) 上的多项式运算 | S-box 求逆、列混合(Ch9) | +| **GHASH(GCM 认证)** | GF(2¹²⁸) 上多项式求值 | AES-GCM 的认证位(Ch9) | | **哈希雪崩** | 输入差 1 bit → 输出差 ~50% bit | 哈希 / HMAC / SYN cookie(Ch8, Ch9) | ### 网络 / 系统 | 名称 | 公式 / 概念 | 在哪一章用上 | |------|------|------| -| **TCP 初始序号** | ISN = M + F(四元组, 密钥) | 防止序号预测(Ch8) | -| **带宽延迟乘积** | BDP = 带宽 × RTT | BBR 拥塞控制的核心(Ch12) | -| **最长前缀匹配** | 路由表里取最具体的前缀 | 路由器转发(Ch5) | -| **一致性哈希** | 节点和请求映射到环 | 负载均衡(Ch10) | -| **Little's Law(排队论)** | L = λ × W(队长 = 到达率 × 平均等待时间) | 路由器队列、TCP / 服务器延迟分析(Ch11, Ch12) | +| **TCP 初始序号** | ISN = M + F(四元组, 密钥) | 防止序号预测(Ch8) | +| **带宽延迟乘积** | BDP = 带宽 × RTT | BBR 拥塞控制的核心(Ch12) | +| **最长前缀匹配** | 路由表里取最具体的前缀 | 路由器转发(Ch5) | +| **一致性哈希** | 节点和请求映射到环 | 负载均衡(Ch10) | +| **Little's Law(排队论)** | L = λ × W(队长 = 到达率 × 平均等待时间) | 路由器队列、TCP / 服务器延迟分析(Ch11, Ch12) | --- @@ -1055,7 +1055,7 @@ Google 服务器生成的响应数据,要走和来时差不多的路径回到你 | 城域网路由器 | 核心路由 | 华为 NE40E/NE9000、思科 ASR9000、Juniper MX | | 路由器转发芯片 | NPU/ASIC | 博通 Jericho 系列、思科 Silicon One | | 数据中心交换机 | 商用交换芯片 | 博通 Tomahawk 系列、Tofino | -| 海底中继器 | 光放大器 | EDFA(SubCom、NEC、华为海洋) | +| 海底中继器 | 光放大器 | EDFA(SubCom、NEC、华为海洋) | | DWDM 设备 | 长距离光传输 | Ciena、华为 OptiX、中兴 ZXMP | | 服务器网卡 | 高性能 NIC | NVIDIA Mellanox ConnectX、Intel E810、Google 自研 | | 服务器 DPU | 智能网卡 | NVIDIA BlueField、AWS Nitro、Intel IPU | @@ -1067,216 +1067,216 @@ Google 服务器生成的响应数据,要走和来时差不多的路径回到你 > 这一节是为了让你**以"原理"为索引、横向看穿整条链路**。每一行只用一句话讲清楚"它在哪一章用上、它告诉我们什么"。需要细节再回正文找。 -### 一、电磁与光(物理学) +### 一、电磁与光(物理学) | 原理 | 一句话 | 用在哪 | |------|--------|------| -| **Maxwell 方程组**(1865) | 电场和磁场互相激发,以光速向四周扩散——所有电磁波的存在凭据 | Ch3 5G、Ch5 光纤、Ch7 海底光缆、Wi-Fi、雷达、GPS | +| **Maxwell 方程组**(1865) | 电场和磁场互相激发,以光速向四周扩散——所有电磁波的存在凭据 | Ch3 5G、Ch5 光纤、Ch7 海底光缆、Wi-Fi、雷达、GPS | | **光速恒定** `c ≈ 3×10⁸ m/s` | 真空中电磁波速度的硬上限 | RTT 下限的物理根 | -| **频率 / 波长 `c = λf`** | 频率越高,波长越短,天线越小 | 5G 频段选择、毫米波天线阵 | -| **全反射(斯涅尔定律)** | 光从高折射率介质射向低折射率,角度足够大就被弹回去 | 光纤几乎不漏光的原因 | -| **波的相干叠加(Young,1801)** | 同相位相加,反相位抵消 | Massive MIMO 波束赋形 | +| **频率 / 波长 `c = λf`** | 频率越高,波长越短,天线越小 | 5G 频段选择、毫米波天线阵 | +| **全反射(斯涅尔定律)** | 光从高折射率介质射向低折射率,角度足够大就被弹回去 | 光纤几乎不漏光的原因 | +| **波的相干叠加(Young,1801)** | 同相位相加,反相位抵消 | Massive MIMO 波束赋形 | | **多普勒效应** | 相对速度造成频率偏移 | 高铁 / 卫星通信里要补偿 | -### 二、量子与半导体(物理学) +### 二、量子与半导体(物理学) | 原理 | 一句话 | 用在哪 | |------|--------|------| -| **能带理论 / MOSFET 反型层** | 电场把电子推到导带,通道形成 / 消失 → 数字 0/1 | 所有芯片里的晶体管开关 | -| **量子隧穿** | 电子有概率"穿过"足够薄的绝缘层 | 工艺微缩到 3nm 时的漏电墙;闪存擦写 | -| **光子(普朗克 / 爱因斯坦)** | 光以 `hf` 大小一份份的能量传递 | 光纤接收灵敏度的物理下限 | -| **受激辐射(爱因斯坦,1917)** | 一个入射光子诱导出一个完全相同的新光子 | 激光器、EDFA 全光放大 | -| **粒子数反转** | 高能级电子比低能级多,才能净放大 | EDFA 工作前提 | +| **能带理论 / MOSFET 反型层** | 电场把电子推到导带,通道形成 / 消失 → 数字 0/1 | 所有芯片里的晶体管开关 | +| **量子隧穿** | 电子有概率"穿过"足够薄的绝缘层 | 工艺微缩到 3nm 时的漏电墙;闪存擦写 | +| **光子(普朗克 / 爱因斯坦)** | 光以 `hf` 大小一份份的能量传递 | 光纤接收灵敏度的物理下限 | +| **受激辐射(爱因斯坦,1917)** | 一个入射光子诱导出一个完全相同的新光子 | 激光器、EDFA 全光放大 | +| **粒子数反转** | 高能级电子比低能级多,才能净放大 | EDFA 工作前提 | -### 三、信号处理与信息论(数学) +### 三、信号处理与信息论(数学) | 原理 | 一句话 | 用在哪 | |------|--------|------| | **傅里叶变换** | 任何信号都能拆成不同频率正弦波的叠加 | OFDM、调制解调、色散补偿、数字滤波 | -| **快速傅里叶变换(FFT)** | 把 O(N²) 算法降到 O(N log N) | 让 OFDM 在硬件里实时跑得动 | -| **采样定理(奈奎斯特)** | 采样频率至少是最高频率的 2 倍才能不失真 | ADC / DAC 的设计基础 | +| **快速傅里叶变换(FFT)** | 把 O(N²) 算法降到 O(N log N) | 让 OFDM 在硬件里实时跑得动 | +| **采样定理(奈奎斯特)** | 采样频率至少是最高频率的 2 倍才能不失真 | ADC / DAC 的设计基础 | | **香农信道容量** `C = B log₂(1+SNR)` | 一个信道每秒最多能传多少信息 | LDPC / Polar / 编码增益的天花板 | -| **前向纠错(代数构造)** | 加冗余,接收端用代数运算修正错误 | Reed-Solomon、LDPC、Polar、SD-FEC | -| **CRC** | 多项式除法做校验,极快、检错强 | 各层错误检测 | +| **前向纠错(代数构造)** | 加冗余,接收端用代数运算修正错误 | Reed-Solomon、LDPC、Polar、SD-FEC | +| **CRC** | 多项式除法做校验,极快、检错强 | 各层错误检测 | -### 四、密码学(数论 + 群论 + 有限域 + 复杂性) +### 四、密码学(数论 + 群论 + 有限域 + 复杂性) | 原理 | 一句话 | 用在哪 | |------|--------|------| -| **质数无穷性(欧几里得)** | 我们永远找得到 2048 位的大质数 | 所有公钥密码的根材料 | +| **质数无穷性(欧几里得)** | 我们永远找得到 2048 位的大质数 | 所有公钥密码的根材料 | | **模幂运算 / 欧拉定理** | `g^a mod p` 用快速幂可在毫秒内算完 | RSA、Diffie-Hellman 的"正向" | -| **离散对数难题(DLP)** | 反推 `a` 目前还没有多项式时间算法 | 让 RSA / DH 安全的"反向"难度 | -| **椭圆曲线 / ECDLP** | 把群结构换到曲线上,同样难 + 更紧凑 | TLS 1.3 的 ECDHE 默认选项 | +| **离散对数难题(DLP)** | 反推 `a` 目前还没有多项式时间算法 | 让 RSA / DH 安全的"反向"难度 | +| **椭圆曲线 / ECDLP** | 把群结构换到曲线上,同样难 + 更紧凑 | TLS 1.3 的 ECDHE 默认选项 | | **有限域 GF(2⁸) / GF(2¹²⁸)** | 字节运算被定义在一个非常对称的代数结构里 | AES 列混合、GHASH 认证 | -| **单向函数 / 哈希雪崩** | 正向算容易,反向找原像不可行;改 1 比特 → 输出全变 | SHA-256、HMAC、SYN cookie、git commit | -| **计算复杂性假设** | 我们"相信"P ≠ NP,某些问题没有捷径 | 整套现代密码安全的隐含前提 | +| **单向函数 / 哈希雪崩** | 正向算容易,反向找原像不可行;改 1 比特 → 输出全变 | SHA-256、HMAC、SYN cookie、git commit | +| **计算复杂性假设** | 我们"相信"P ≠ NP,某些问题没有捷径 | 整套现代密码安全的隐含前提 | | **Shor 算法的威胁** | 量子计算机能在多项式时间破 RSA / ECC | 后量子密码、混合密钥交换的推动力 | -### 五、网络与系统(图论 / 排队论 / 概率) +### 五、网络与系统(图论 / 排队论 / 概率) | 原理 | 一句话 | 用在哪 | |------|--------|------| | **图论最短路径** | BGP / OSPF / IS-IS 算的就是图上的"最优路径" | 互联网路由 | -| **最长前缀匹配** | 选最具体的那条规则,数据结构上是 trie | 路由器转发表查找 | -| **一致性哈希** | 节点 / 请求都丢到一个圆环上,加减节点扰动最小 | Maglev 负载均衡、分布式存储 | +| **最长前缀匹配** | 选最具体的那条规则,数据结构上是 trie | 路由器转发表查找 | +| **一致性哈希** | 节点 / 请求都丢到一个圆环上,加减节点扰动最小 | Maglev 负载均衡、分布式存储 | | **Little's Law** `L = λ × W` | 队长 = 到达率 × 平均等待时间——任何稳态队列都满足 | 路由器、网卡队列、TCP 拥塞、服务器延迟 | -| **指数退避** | 失败次数 n,重试间隔翻倍 | Wi-Fi、TCP 重传、限流 | -| **分布式共识(两军 / FLP)** | 完全可靠的握手在异步网络里被证明不可能 | TCP 三次握手为何"够用就好" | +| **指数退避** | 失败次数 n,重试间隔翻倍 | Wi-Fi、TCP 重传、限流 | +| **分布式共识(两军 / FLP)** | 完全可靠的握手在异步网络里被证明不可能 | TCP 三次握手为何"够用就好" | ### 六、工程上的"快速做出来" | 原理 | 一句话 | 用在哪 | |------|--------|------| -| **缓存层级 + 局部性** | 越靠近 CPU 越快,概率上多次访问"附近"地址 | L1/L2/L3 cache、TCP 重组缓冲 | +| **缓存层级 + 局部性** | 越靠近 CPU 越快,概率上多次访问"附近"地址 | L1/L2/L3 cache、TCP 重组缓冲 | | **流水线 + 并行** | 把单步串行的工作分阶段同时跑 | CPU、转发 ASIC、OFDM 处理流水 | -| **专用电路(ASIC / FPGA)** | 把一种特定运算硬化成电路,牺牲灵活换性能 | 路由器转发、矿机、AI 加速、AES-NI | +| **专用电路(ASIC / FPGA)** | 把一种特定运算硬化成电路,牺牲灵活换性能 | 路由器转发、矿机、AI 加速、AES-NI | -把这六张表横着读,可以看到一件事:**这条链路不是 6 个领域的加法,而是 6 套数学 / 物理体系互相咬合的产物**。少了任意一个,你今天的天气查询就跑不通——香农定理给你"理论上能多快",量子力学给你"硅片为什么能开关",数论给你"为什么别人偷不走",图论给你"包应该往哪走"。 +把这六张表横着读,可以看到一件事:**这条链路不是 6 个领域的加法,而是 6 套数学 / 物理体系互相咬合的产物**。少了任意一个,你今天的天气查询就跑不通——香农定理给你"理论上能多快",量子力学给你"硅片为什么能开关",数论给你"为什么别人偷不走",图论给你"包应该往哪走"。 --- ## 附录 D 那些"刚刚好"的巧合 -这条链路能跑得这么稳、这么快、这么便宜,有一些是工程师推动的,但也有几样是物理世界本身"恰好"有的安排——少了任何一项,今天的互联网都会长得很不一样。 +这条链路能跑得这么稳、这么快、这么便宜,有一些是工程师推动的,但也有几样是物理世界本身"恰好"有的安排——少了任何一项,今天的互联网都会长得很不一样。 ### 一、1550 nm 恰好处于光纤的"最低损耗窗口" -二氧化硅(石英玻璃)对不同波长的光有不同的衰减:可见光大约 100 dB/km(完全没法跑长距离),近红外 850 nm 大约 2 dB/km,1310 nm 大约 0.35 dB/km,**1550 nm 只有约 0.2 dB/km**——这是一个由石英玻璃的瑞利散射(短波端损耗主因)+ 红外吸收(长波端损耗主因)共同决定的**自然窗口**,不是工程师选的。 +二氧化硅(石英玻璃)对不同波长的光有不同的衰减:可见光大约 100 dB/km(完全没法跑长距离),近红外 850 nm 大约 2 dB/km,1310 nm 大约 0.35 dB/km,**1550 nm 只有约 0.2 dB/km**——这是一个由石英玻璃的瑞利散射(短波端损耗主因)+ 红外吸收(长波端损耗主因)共同决定的**自然窗口**,不是工程师选的。 -更"凑巧"的是,**EDFA(掺铒光纤放大器)的工作波段恰好在 1530-1565 nm**——铒离子的能级跃迁波长和石英玻璃的最低损耗窗口几乎完美重合。所以一根纯光学放大的长距离光纤天然有效。如果铒离子的能级结构落在别处,海底光缆的成本和容量都会差几个数量级——**EDFA + 1550 nm 这一对组合,是物理给我们的一个免费午餐**。 +更"凑巧"的是,**EDFA(掺铒光纤放大器)的工作波段恰好在 1530-1565 nm**——铒离子的能级跃迁波长和石英玻璃的最低损耗窗口几乎完美重合。所以一根纯光学放大的长距离光纤天然有效。如果铒离子的能级结构落在别处,海底光缆的成本和容量都会差几个数量级——**EDFA + 1550 nm 这一对组合,是物理给我们的一个免费午餐**。 -DWDM 把几十个波长塞进 1530-1610 nm 窗口同时跑,本质就是"在物理给的这个窗口里,把每个色块都用上"。 +DWDM 把几十个波长塞进 1530-1610 nm 窗口同时跑,本质就是"在物理给的这个窗口里,把每个色块都用上"。 ### 二、地球曲率半径恰好让低频电波"贴地传几百公里" -电磁波在地球上的传播路径,取决于频率: +电磁波在地球上的传播路径,取决于频率: -- **高频(GHz 量级,5G、Wi-Fi、卫星)**:几乎是直线传播,被建筑遮挡就没,需要密集基站补盲 -- **中频(MHz 量级,中波广播)**:可以绕地表传几百公里,白天靠地波,夜晚靠电离层 D 层吸收减弱后的天波 -- **低频 / 短波(几 MHz - 几十 MHz)**:能在地表和电离层之间反射,跳几次传几千上万公里 -- **极低频(VLF / ELF)**:能透入海水几十米,潜艇通信靠这个 +- **高频(GHz 量级,5G、Wi-Fi、卫星)**:几乎是直线传播,被建筑遮挡就没,需要密集基站补盲 +- **中频(MHz 量级,中波广播)**:可以绕地表传几百公里,白天靠地波,夜晚靠电离层 D 层吸收减弱后的天波 +- **低频 / 短波(几 MHz - 几十 MHz)**:能在地表和电离层之间反射,跳几次传几千上万公里 +- **极低频(VLF / ELF)**:能透入海水几十米,潜艇通信靠这个 -**地球半径 6371 km 给了一个特定的曲率,大气层的电离层(60-1000 km 高度)恰好在这个尺度上方反射特定频段的电波**。这两个尺度共同决定了"哪些频段能贴地传、哪些能反射、哪些只能直线传"。 +**地球半径 6371 km 给了一个特定的曲率,大气层的电离层(60-1000 km 高度)恰好在这个尺度上方反射特定频段的电波**。这两个尺度共同决定了"哪些频段能贴地传、哪些能反射、哪些只能直线传"。 -如果地球小一倍、大一倍,或者电离层位置不同,无线电传播规律就完全不一样——HF 短波"全球覆盖"的便宜手段可能根本不存在。5G 工程师选载频时其实没多少自由度:选低了波长太长、天线没法做小;选高了大气吸收太重、传不了几米。**能用的窗口是地球大气和地表曲率给的**。 +如果地球小一倍、大一倍,或者电离层位置不同,无线电传播规律就完全不一样——HF 短波"全球覆盖"的便宜手段可能根本不存在。5G 工程师选载频时其实没多少自由度:选低了波长太长、天线没法做小;选高了大气吸收太重、传不了几米。**能用的窗口是地球大气和地表曲率给的**。 -### 三、硅(Silicon)的能带宽度恰好适合做晶体管 +### 三、硅(Silicon)的能带宽度恰好适合做晶体管 -硅原子最外层 4 个电子,能带间隙 1.12 eV——**这个数值大到常温下不会"自激活"乱开关,小到电场容易控制让它开关**。 +硅原子最外层 4 个电子,能带间隙 1.12 eV——**这个数值大到常温下不会"自激活"乱开关,小到电场容易控制让它开关**。 -- 间隙更大(比如金刚石,5.5 eV):开关需要更高电压,功耗爆炸 -- 间隙更小(比如锗,0.67 eV):漏电严重,温度稍高就失控 +- 间隙更大(比如金刚石,5.5 eV):开关需要更高电压,功耗爆炸 +- 间隙更小(比如锗,0.67 eV):漏电严重,温度稍高就失控 -地球地壳里 28% 是硅,几乎是仅次于氧的第二多元素。**地球恰好给了我们一种性质刚好、储量极大、提纯不太难的半导体材料**——整个微电子工业能这么便宜地做出来,这是前提。 +地球地壳里 28% 是硅,几乎是仅次于氧的第二多元素。**地球恰好给了我们一种性质刚好、储量极大、提纯不太难的半导体材料**——整个微电子工业能这么便宜地做出来,这是前提。 ### 四、真空光速给的 RTT 是"刚好可以做实时交互"的尺度 -光速 30 万公里 / 秒。地球周长 4 万公里。**绕地球一圈最快也要 130 ms**(实际跨洋链路加上路由器排队,普遍 150-200 ms)。 +光速 30 万公里 / 秒。地球周长 4 万公里。**绕地球一圈最快也要 130 ms**(实际跨洋链路加上路由器排队,普遍 150-200 ms)。 -这个数字恰好在人类感知的边缘:130-200 ms 的延迟,人脑能感觉到"有点延迟"但还能接受;真要是光速慢一千倍,远程操作、在线游戏、视频通话都会变得不可能;真要是快一千倍,GPS 卫星和地面的同步都不需要广义相对论那么复杂的修正了。 +这个数字恰好在人类感知的边缘:130-200 ms 的延迟,人脑能感觉到"有点延迟"但还能接受;真要是光速慢一千倍,远程操作、在线游戏、视频通话都会变得不可能;真要是快一千倍,GPS 卫星和地面的同步都不需要广义相对论那么复杂的修正了。 -**我们这个时代能搞出"全球实时通信"的互联网,本质上是因为光速给的全球 RTT 上限恰好压在人类感知边界上**——快一点没必要、慢一点不可用,刚刚好。 +**我们这个时代能搞出"全球实时通信"的互联网,本质上是因为光速给的全球 RTT 上限恰好压在人类感知边界上**——快一点没必要、慢一点不可用,刚刚好。 ### 五、大整数分解 / 离散对数恰好"做容易、算难" -这一条不是物理凑巧,是**数学凑巧**——而且更脆弱: +这一条不是物理凑巧,是**数学凑巧**——而且更脆弱: -- 至少从今天的数学水平看:**找两个 1024 位质数相乘**用现代 CPU 几毫秒就行;**反过来,把它们乘出来的 2048 位数分解回去**,目前最强的算法(GNFS)需要全球算力跑几十年 -- 这条不对称性是 §9 整套公钥密码学的**全部根基**。如果数论里有人找到一个高效分解算法,整个 HTTPS 当晚就崩 -- **Shor 算法已经证明:量子计算机能在多项式时间内分解大整数**。所以这条"刚好"是有有效期的——它有效是因为足够大的量子计算机还没造出来 +- 至少从今天的数学水平看:**找两个 1024 位质数相乘**用现代 CPU 几毫秒就行;**反过来,把它们乘出来的 2048 位数分解回去**,目前最强的算法(GNFS)需要全球算力跑几十年 +- 这条不对称性是 §9 整套公钥密码学的**全部根基**。如果数论里有人找到一个高效分解算法,整个 HTTPS 当晚就崩 +- **Shor 算法已经证明:量子计算机能在多项式时间内分解大整数**。所以这条"刚好"是有有效期的——它有效是因为足够大的量子计算机还没造出来 -更深一层:**P ≠ NP** 这个支撑现代密码安全的核心猜想,我们其实没有证明,只是"几十年没人找到反例就当成立"。整个互联网的"私"字,压在一条**未被证明的数学猜想**上。 +更深一层:**P ≠ NP** 这个支撑现代密码安全的核心猜想,我们其实没有证明,只是"几十年没人找到反例就当成立"。整个互联网的"私"字,压在一条**未被证明的数学猜想**上。 -### 六、可见光带的位置:恰好不被大气吸收、恰好能被生物利用 +### 六、可见光带的位置:恰好不被大气吸收、恰好能被生物利用 -这条不直接和互联网有关,但顺手一提: +这条不直接和互联网有关,但顺手一提: -太阳光谱大部分被大气吸收(紫外被臭氧、远红外被水汽和 CO₂),**唯独可见光 + 近红外波段是"大气透明窗口"**——所以光合作用、人类视觉、光纤通信(1550 nm 在近红外里)都聚集在这个频段附近。 +太阳光谱大部分被大气吸收(紫外被臭氧、远红外被水汽和 CO₂),**唯独可见光 + 近红外波段是"大气透明窗口"**——所以光合作用、人类视觉、光纤通信(1550 nm 在近红外里)都聚集在这个频段附近。 -这不是巧合的工程后果——是**生物从一开始就利用了这个窗口进化出视觉**(所以叫"可见光"),而工程师们后来又把光纤通信塞到了同一个窗口的红外侧。物理世界给的窗口决定了生命的视觉范围,也决定了我们的通信范围。 +这不是巧合的工程后果——是**生物从一开始就利用了这个窗口进化出视觉**(所以叫"可见光"),而工程师们后来又把光纤通信塞到了同一个窗口的红外侧。物理世界给的窗口决定了生命的视觉范围,也决定了我们的通信范围。 --- -**总结**:互联网看起来是"人造的奇迹",但仔细一层层剥开,会发现下面几乎每一层的可行性,都依赖一个"宇宙恰好这样"——光纤恰好在 1550 nm 损耗最低,地球曲率恰好让无线电能绕弯,硅的能带恰好能做晶体管,光速恰好快得够实时通信但慢得需要拥塞控制,数论里恰好存在"做容易算难"的不对称性。 +**总结**:互联网看起来是"人造的奇迹",但仔细一层层剥开,会发现下面几乎每一层的可行性,都依赖一个"宇宙恰好这样"——光纤恰好在 1550 nm 损耗最低,地球曲率恰好让无线电能绕弯,硅的能带恰好能做晶体管,光速恰好快得够实时通信但慢得需要拥塞控制,数论里恰好存在"做容易算难"的不对称性。 -少任何一样,这条链路就根本不会以今天的方式存在。**人类的工程努力是把这些"刚刚好"接起来——而不是创造它们。** +少任何一样,这条链路就根本不会以今天的方式存在。**人类的工程努力是把这些"刚刚好"接起来——而不是创造它们。** --- ## 写在最后 -下次你打开手机搜个天气、刷个微博、看个视频,可以想想:这个看似平淡的动作,背后有几十亿个晶体管在切换、有激光脉冲在万里之外的海底光纤里飞驰、有几十种数学算法在保证你的数据准确无误地到达、有几代工程师设计的协议层层协作。 +下次你打开手机搜个天气、刷个微博、看个视频,可以想想:这个看似平淡的动作,背后有几十亿个晶体管在切换、有激光脉冲在万里之外的海底光纤里飞驰、有几十种数学算法在保证你的数据准确无误地到达、有几代工程师设计的协议层层协作。 -互联网真正神奇的地方不是它有多快,而是它居然能这样工作——而且对绝大多数用户来说,完全透明。 +互联网真正神奇的地方不是它有多快,而是它居然能这样工作——而且对绝大多数用户来说,完全透明。 --- -### 未完待续:接下来十年的链路会怎么变 +### 未完待续:接下来十年的链路会怎么变 -这条链路不是完成态。几乎每一层都在继续演化,你这代人的有生之年会亲眼看到它们换一遍: +这条链路不是完成态。几乎每一层都在继续演化,你这代人的有生之年会亲眼看到它们换一遍: -- **物理层**:更高频段(亚 THz、光通信)、低轨卫星互联网(Starlink 这类)正在重塑"无线"。**空芯光纤**(光子晶体光纤)可能让光速重新回到接近真空中的 30 万 km/s,而不是现在的 20 万——跨洋 RTT 因此可能下降三分之一 -- **网络层**:**IPv6** 终于在普及,IPv4 还死不掉,两者会长期并存。BGP 的安全顽疾(路由劫持、泄漏)正用 **RPKI** 慢慢补 -- **传输层**:**HTTP/3 + QUIC** 把 TLS、TCP、多路复用揉成一个新协议,正在大量替换 HTTPS over TCP。对手机用户来说,这意味着弱网和切换网络时加载更稳 -- **加密层**:**后量子密码(PQC)** 已经进入 TLS 1.3 实测,Cloudflare 2024 年起在全网启用混合 ECDHE+Kyber。我们这代人会在自己的有生之年亲历一次**大规模密码体系迁移**——上一次是 RSA→ECC,下一次是 ECC→PQC,触发因素是量子计算的逐步成熟 -- **服务器层**:CPU 让位给 **DPU + AI 加速器**。更深一层的变化是**流量本身的形态变了**——AI 推理流量(ChatGPT 这种)单次请求消耗的算力、产生的下行流量,和传统网页搜索差几个数量级,数据中心的设计正在被重写 -- **审查与反审查**:GFW 加上 ECH 拦截、机器学习流量识别,Reality 加上流量混淆、对抗样本生成——猫鼠游戏会在更高维度继续 +- **物理层**:更高频段(亚 THz、光通信)、低轨卫星互联网(Starlink 这类)正在重塑"无线"。**空芯光纤**(光子晶体光纤)可能让光速重新回到接近真空中的 30 万 km/s,而不是现在的 20 万——跨洋 RTT 因此可能下降三分之一 +- **网络层**:**IPv6** 终于在普及,IPv4 还死不掉,两者会长期并存。BGP 的安全顽疾(路由劫持、泄漏)正用 **RPKI** 慢慢补 +- **传输层**:**HTTP/3 + QUIC** 把 TLS、TCP、多路复用揉成一个新协议,正在大量替换 HTTPS over TCP。对手机用户来说,这意味着弱网和切换网络时加载更稳 +- **加密层**:**后量子密码(PQC)** 已经进入 TLS 1.3 实测,Cloudflare 2024 年起在全网启用混合 ECDHE+Kyber。我们这代人会在自己的有生之年亲历一次**大规模密码体系迁移**——上一次是 RSA→ECC,下一次是 ECC→PQC,触发因素是量子计算的逐步成熟 +- **服务器层**:CPU 让位给 **DPU + AI 加速器**。更深一层的变化是**流量本身的形态变了**——AI 推理流量(ChatGPT 这种)单次请求消耗的算力、产生的下行流量,和传统网页搜索差几个数量级,数据中心的设计正在被重写 +- **审查与反审查**:GFW 加上 ECH 拦截、机器学习流量识别,Reality 加上流量混淆、对抗样本生成——猫鼠游戏会在更高维度继续 -如果 30 年后有人再写这篇文档,**章节大概还是这些章节,但每一章里的具体技术都会不同**。物理定律不变(Maxwell、量子、香农),数学根基不变(数论、群论、有限域),工程层面会换好几代人。 +如果 30 年后有人再写这篇文档,**章节大概还是这些章节,但每一章里的具体技术都会不同**。物理定律不变(Maxwell、量子、香农),数学根基不变(数论、群论、有限域),工程层面会换好几代人。 --- ### 一条线上的几代人 -这条链路最让人感慨的地方,不只是它涉及多少种技术,而是——这条链上的每一环,是不同的人、在不同的时代、在世界不同的角落做出来的。他们彼此往往**素不相识**,甚至**互不知道对方在做什么**。 +这条链路最让人感慨的地方,不只是它涉及多少种技术,而是——这条链上的每一环,是不同的人、在不同的时代、在世界不同的角落做出来的。他们彼此往往**素不相识**,甚至**互不知道对方在做什么**。 -**克劳德·香农(Claude Shannon)** 1948 年在贝尔实验室发表《通信的数学理论》,推出了那个简洁的**香农信道容量公式**。他不知道这个公式七十年后会决定你的手机能不能在地铁里加载视频。 +**克劳德·香农(Claude Shannon)** 1948 年在贝尔实验室发表《通信的数学理论》,推出了那个简洁的**香农信道容量公式**。他不知道这个公式七十年后会决定你的手机能不能在地铁里加载视频。 -**惠特菲尔德·迪菲(Whitfield Diffie)** 和 **马丁·赫尔曼(Martin Hellman)** 1976 年发表 **Diffie-Hellman** 论文,他们的初衷是"密码学不应该只属于政府和军方"。他们没法预见三十年后全世界几十亿人每一次刷网页都在用他们的数学。 +**惠特菲尔德·迪菲(Whitfield Diffie)** 和 **马丁·赫尔曼(Martin Hellman)** 1976 年发表 **Diffie-Hellman** 论文,他们的初衷是"密码学不应该只属于政府和军方"。他们没法预见三十年后全世界几十亿人每一次刷网页都在用他们的数学。 -设计 TCP 的 **Vint Cerf** 和 **Bob Kahn**,1974 年在斯坦福写下那份协议草案的时候,根本没想过它会演化出 **BBR** 这种拥塞控制算法,更不会想到它会跑在一万米深的海底光缆里。 +设计 TCP 的 **Vint Cerf** 和 **Bob Kahn**,1974 年在斯坦福写下那份协议草案的时候,根本没想过它会演化出 **BBR** 这种拥塞控制算法,更不会想到它会跑在一万米深的海底光缆里。 -发明**掺铒光纤放大器(EDFA)**的 **David Payne**,1986 年在南安普顿大学搞研究的时候,大概也没想到这个东西会沉在太平洋海底——让你在咖啡馆里查个天气,顺顺当当。 +发明**掺铒光纤放大器(EDFA)**的 **David Payne**,1986 年在南安普顿大学搞研究的时候,大概也没想到这个东西会沉在太平洋海底——让你在咖啡馆里查个天气,顺顺当当。 -更早一点的几位,自己根本没看到这条链路: +更早一点的几位,自己根本没看到这条链路: -- **詹姆斯·克拉克·麦克斯韦(James Clerk Maxwell)** 1865 年写下那四条方程,他相信电磁波存在,但 1879 年去世时世界上还没人造出过无线电 -- **阿尔伯特·爱因斯坦(Albert Einstein)** 1917 年提出**受激辐射**,纯粹是为了把光的量子统计算清楚,激光器是 43 年后才被造出来的 -- **欧拉(Leonhard Euler)** 18 世纪研究的费马小定理 / 欧拉定理,两百多年后成了 RSA 和 Diffie-Hellman 的代数地基 +- **詹姆斯·克拉克·麦克斯韦(James Clerk Maxwell)** 1865 年写下那四条方程,他相信电磁波存在,但 1879 年去世时世界上还没人造出过无线电 +- **阿尔伯特·爱因斯坦(Albert Einstein)** 1917 年提出**受激辐射**,纯粹是为了把光的量子统计算清楚,激光器是 43 年后才被造出来的 +- **欧拉(Leonhard Euler)** 18 世纪研究的费马小定理 / 欧拉定理,两百多年后成了 RSA 和 Diffie-Hellman 的代数地基 -更有意思的是,这些人很多都不是为了"造互联网"而工作的: +更有意思的是,这些人很多都不是为了"造互联网"而工作的: - 香农是为了搞清楚"通信的本质是什么" - 迪菲是为了"对抗政府对密码学的垄断" -- **Reed 和 Solomon** 1960 年发明纠错码,是为了一个"理论上有趣的代数问题" -- **椭圆曲线**密码学的源头可以追溯到 19 世纪数学家研究椭圆函数,纯粹的"无用之学" +- **Reed 和 Solomon** 1960 年发明纠错码,是为了一个"理论上有趣的代数问题" +- **椭圆曲线**密码学的源头可以追溯到 19 世纪数学家研究椭圆函数,纯粹的"无用之学" -然后某一天,某个工程师翻到一篇几十年前的数学论文,说"嘿,这个东西好像可以解决我手头的问题"——于是这些散落在各个角落的智慧,就被一点一点拼到了一起。 +然后某一天,某个工程师翻到一篇几十年前的数学论文,说"嘿,这个东西好像可以解决我手头的问题"——于是这些散落在各个角落的智慧,就被一点一点拼到了一起。 -这条链上还有无数没有名字的人:画 ASIC 版图的工程师、调试基站射频的工程师、运维海底光缆的水手、写 Linux 内核网络栈那几万行代码的志愿者、第一次把 BGP 路由表配通的网管。他们大部分人不会出现在任何历史书里。 +这条链上还有无数没有名字的人:画 ASIC 版图的工程师、调试基站射频的工程师、运维海底光缆的水手、写 Linux 内核网络栈那几万行代码的志愿者、第一次把 BGP 路由表配通的网管。他们大部分人不会出现在任何历史书里。 -但你点一下手机,他们几代人的工作,就全部在那 300 毫秒里默默完成了一遍。 +但你点一下手机,他们几代人的工作,就全部在那 300 毫秒里默默完成了一遍。 -科幻作家 **Arthur C. Clarke** 说过一句话:"任何足够先进的技术,都与魔法无异。"我们今天习以为常的事情——按一下屏幕,半个地球外的信息就出现在眼前——如果让 100 年前的人看到,他们大概率会认为这是某种神迹。 +科幻作家 **Arthur C. Clarke** 说过一句话:"任何足够先进的技术,都与魔法无异。"我们今天习以为常的事情——按一下屏幕,半个地球外的信息就出现在眼前——如果让 100 年前的人看到,他们大概率会认为这是某种神迹。 -但它不是神迹。它是一群人,在一百多年的时间里,一砖一瓦垒起来的。 +但它不是神迹。它是一群人,在一百多年的时间里,一砖一瓦垒起来的。 -我们这代人是站在一座大山上的。这座山是无数前人用毕生心血堆出来的——他们中的大多数,从未谋面,也未必都能等到自己的那一砖被用上的那一天。 +我们这代人是站在一座大山上的。这座山是无数前人用毕生心血堆出来的——他们中的大多数,从未谋面,也未必都能等到自己的那一砖被用上的那一天。 -能在这个时代生活,本身就是一件很幸运的事。 +能在这个时代生活,本身就是一件很幸运的事。 --- -### 尾声:回到那个咖啡馆门口 +### 尾声:回到那个咖啡馆门口 -那个站在上海咖啡馆门口的你,看完天气,锁屏,把手机塞回口袋,推门走进去,点了一杯咖啡。 +那个站在上海咖啡馆门口的你,看完天气,锁屏,把手机塞回口袋,推门走进去,点了一杯咖啡。 -店里的 Wi-Fi 自动连上了——后台又跑了一遍 DHCP、ARP、DNS、TCP、TLS、HTTP。你点单的小程序加载出来,扫码付款的二维码刷新了一下——后台又跑了一遍 HTTPS、签名验证、银行接口、风控模型。咖啡店的音响里放着一首歌,从某个 CDN 边缘节点流过来——后台又跑了一遍 QUIC、自适应码率、CDN 路由。 +店里的 Wi-Fi 自动连上了——后台又跑了一遍 DHCP、ARP、DNS、TCP、TLS、HTTP。你点单的小程序加载出来,扫码付款的二维码刷新了一下——后台又跑了一遍 HTTPS、签名验证、银行接口、风控模型。咖啡店的音响里放着一首歌,从某个 CDN 边缘节点流过来——后台又跑了一遍 QUIC、自适应码率、CDN 路由。 -每一件你已经完全不会去想的事情,都还是这同一个奇迹的延续。 +每一件你已经完全不会去想的事情,都还是这同一个奇迹的延续。 只是你已经不再注意了。 **这就是好工程的最终形态——它好到让你忘了它存在**。 -而这篇文章,只不过是把那一两秒钟里你忘掉的东西,慢慢地、再讲一遍。 +而这篇文章,只不过是把那一两秒钟里你忘掉的东西,慢慢地、再讲一遍。 diff --git a/content/posts/2026-05-02-ai-engineer-map.md b/content/posts/2026-05-02-ai-engineer-map.md index 6f25535..153f6f4 100644 --- a/content/posts/2026-05-02-ai-engineer-map.md +++ b/content/posts/2026-05-02-ai-engineer-map.md @@ -4,11 +4,11 @@ date: 2026-05-02 slug: ai-engineer-map tags: ["AI", "LLM", "Prompt", "RAG", "MCP", "Agent", "Claude", "Cursor", "Ollama"] categories: ["AI"] -description: "从大模型 / Prompt / RAG / MCP / Agent / 多模态 / 成本控制 / 编码工具一路捋下来,适合有技术背景的开发者快速建立 AI 知识框架。" +description: "从大模型 / Prompt / RAG / MCP / Agent / 多模态 / 成本控制 / 编码工具一路捋下来,适合有技术背景的开发者快速建立 AI 知识框架。" draft: false --- -> 适合有一定技术背景的开发者快速建立 AI 知识框架。涵盖核心概念、工程实践、工具选型,持续更新。 +> 适合有一定技术背景的开发者快速建立 AI 知识框架。涵盖核心概念、工程实践、工具选型,持续更新。 --- diff --git a/scripts/cn-punct.py b/scripts/cn-punct.py new file mode 100644 index 0000000..82b71a5 --- /dev/null +++ b/scripts/cn-punct.py @@ -0,0 +1,390 @@ +"""Convert ASCII punctuation to Chinese punctuation in CJK context. + +Strategy: + - Skip fenced code blocks entirely. + - Mask out inline code, markdown links, bare URLs as opaque blobs (placeholder + char from the Private Use Area), so paren matching can span them. + - Process YAML front matter only by converting `description:` / `title:` / + `summary:` string values — leaves `tags: [...]` arrays alone. + - For each prose line in the body, decide if it's "Chinese-flavored" (>= 3 CJK + chars). On Chinese lines, convert ASCII , . : ; ? ! ( ) → Chinese + counterparts where it makes sense. + +Preservation rules (kept as ASCII): + - Number lists / decimals: `1,234`, `RS(255, 239)`, `1:8` (ratio). + - Math context: a comma/colon between two math expressions (one of `∇ ∂ √ + ≡ ≈ ± ¹²³⁴⁵⁶⁷⁸⁹⁰ ₀₁₂₃₄₅₆₇₈₉` or Greek letters within a 20-char window + on each side). + - Nested inside an existing Chinese paren: only converts prose-like content + (no math/digit indicator), preserving notation like `(GF(2⁸) 列混合)`. + - English-attached parens: `DNS(Domain Name System)` (the `(` immediately + follows an English letter/digit) stays ASCII. + - Inside ASCII parens we chose to keep ASCII (e.g. `cookie(Ch8, Ch9)`), + inner punctuation stays ASCII. + +Usage: + python scripts/cn-punct.py path/to/file1.md path/to/file2.md ... + +This is the one-shot conversion script used in the 2026-05 blog cleanup. It is +deliberately conservative; if you re-run it on already-converted files it +should be a near no-op. +""" +import re +import sys + +CJK_RE = re.compile(r'[一-鿿]') +PLACEHOLDER = '' # private-use char for opaque blobs + +# Walk past these to find the "real" neighbor of a punctuation mark. +WEAK = set(' \t*_"\'`)]}>“”‘’') + +# Punctuation that signals Chinese context for adjacent ASCII punctuation. +CHINESE_PUNCT = set( + ',。:;?!、()' + '【】「」『』' + '“”‘’…—《》〈〉' +) + +# Math-specific characters: superscript / subscript digits, operators, Greek +# letters that almost only appear in formulas. Used to detect comma/colon +# sitting between two math expressions (where it must stay ASCII). +MATH_CHARS = set( + '∇∂√≡≈±' + '¹²³⁴⁵⁶⁷⁸⁹⁰' + '₀₁₂₃₄₅₆₇₈₉' + 'αβγδεζηθικ' + 'λμνξπρστυφ' + 'χψω' + 'ΓΔΘΛΞΠΣΦΨΩ' + '∞∑∏∫·×÷' +) + + +def is_cjk(ch: str) -> bool: + return bool(ch and CJK_RE.match(ch)) + + +def is_chinese_context(ch: str) -> bool: + return is_cjk(ch) or (ch in CHINESE_PUNCT) + + +def is_ascii_alnum(ch: str) -> bool: + return bool(ch) and ord(ch) < 128 and ch.isalnum() + + +def find_strong_neighbor(text: str, idx: int, direction: int) -> str: + """Walk past WEAK chars to find the nearest 'strong' character, or '' if + we hit a boundary.""" + n = len(text) + i = idx + direction + while 0 <= i < n: + ch = text[i] + if ch in WEAK: + i += direction + continue + return ch + return '' + + +def looks_like_math_context(text: str, idx: int, window: int = 20) -> bool: + """Heuristic: comma at idx is between two math expressions if both sides + contain math-specific characters within a small window.""" + left_window = text[max(0, idx - window):idx] + right_window = text[idx + 1:idx + 1 + window] + return ( + any(c in MATH_CHARS for c in left_window) + and any(c in MATH_CHARS for c in right_window) + ) + + +def convert_parens(text: str, aggressive: bool, depth_offset: int = 0) -> str: + """Convert ( ) to ( ) when in Chinese context. + + Tracks Chinese-paren depth so that a paren nested inside an outer Chinese + paren only converts if its own content contains CJK — preserves math + notation like `(GF(2⁸) 列混合)`. + + Skips conversion when the immediate preceding char is an English letter or + digit (e.g. `DNS(Domain Name System)`), since such parens behave like a + function call / abbreviation expansion in the source language. + """ + n = len(text) + out = [] + i = 0 + cn_depth = depth_offset + while i < n: + ch = text[i] + if ch == '(': # ( + cn_depth += 1 + out.append(ch) + i += 1 + continue + if ch == ')': # ) + cn_depth = max(0, cn_depth - 1) + out.append(ch) + i += 1 + continue + if ch == '(': + depth = 1 + j = i + 1 + while j < n and depth > 0: + if text[j] == '(': + depth += 1 + elif text[j] == ')': + depth -= 1 + if depth == 0: + break + j += 1 + if depth == 0: + content = text[i + 1:j] + left = find_strong_neighbor(text, i, -1) + right = find_strong_neighbor(text, j, +1) + immediate_prev = text[i - 1] if i > 0 else '' + content_has_cjk = bool(CJK_RE.search(content)) + neighbor_chinese = ( + is_chinese_context(left) or is_chinese_context(right) + ) + content_has_math = bool(re.search( + r'[\d=+\-*/×÷^¹²³⁴-⁹⁰₀-₉]', + content, + )) + + if cn_depth > 0: + # Nested inside Chinese paren — convert prose-like content + should_convert = content_has_cjk or not content_has_math + elif is_ascii_alnum(immediate_prev): + # Attached to English identifier — leave ASCII + should_convert = content_has_cjk + else: + should_convert = ( + content_has_cjk + or (aggressive and neighbor_chinese) + ) + + inner_offset = cn_depth + (1 if should_convert else 0) + converted_content = convert_parens(content, aggressive, inner_offset) + + if should_convert: + out.append('(') + out.append(converted_content) + out.append(')') + else: + out.append('(') + out.append(converted_content) + out.append(')') + i = j + 1 + continue + out.append(ch) + i += 1 + return ''.join(out) + + +def convert_punct(text: str, aggressive: bool) -> str: + """Convert ASCII , . : ; ? ! to Chinese counterparts. + + Tracks both Chinese-paren depth and ASCII-paren depth: + - Inside `(...)` → aggressive (those are Chinese parentheticals). + - Inside `(...)` → conservative (the surviving ASCII parens were kept + ASCII for a reason — likely English-attached or notation). + """ + chars = list(text) + n = len(chars) + out = [] + cn_paren_depth = 0 + ascii_paren_depth = 0 + for i, ch in enumerate(chars): + if ch == '(': + cn_paren_depth += 1 + out.append(ch) + continue + if ch == ')': + cn_paren_depth = max(0, cn_paren_depth - 1) + out.append(ch) + continue + if ch == '(': + ascii_paren_depth += 1 + out.append(ch) + continue + if ch == ')': + ascii_paren_depth = max(0, ascii_paren_depth - 1) + out.append(ch) + continue + + prev = chars[i - 1] if i > 0 else '' + nxt = chars[i + 1] if i + 1 < n else '' + in_cn_paren = cn_paren_depth > 0 + in_ascii_paren = ascii_paren_depth > 0 + + if ch == ',': + # Number-list separator: digit, [space,] digit → keep ASCII + prev_is_digit = prev.isascii() and prev.isdigit() + after_space_nxt = chars[i + 2] if (nxt == ' ' and i + 2 < n) else nxt + nxt_is_digit = ( + after_space_nxt + and after_space_nxt.isascii() + and after_space_nxt.isdigit() + ) + if prev_is_digit and nxt_is_digit: + out.append(ch) + continue + if looks_like_math_context(text, i): + out.append(ch) + continue + if is_chinese_context(prev) or is_chinese_context(nxt): + out.append(',') + continue + if in_ascii_paren: + out.append(ch) + continue + if in_cn_paren or aggressive: + out.append(',') + continue + elif ch == '.': + if is_ascii_alnum(nxt): + pass # decimal / file ext / version + elif is_chinese_context(prev): + out.append('。') + continue + elif prev in WEAK: + left = find_strong_neighbor(text, i, -1) + if is_chinese_context(left): + out.append('。') + continue + elif ch in (':', ';', '?', '!'): + mapping = {':': ':', ';': ';', '?': '?', '!': '!'} + if ch == ':': + # Ratio / time notation like "1:8" or "12:34" → keep ASCII colon + prev_is_digit = prev.isascii() and prev.isdigit() + nxt_is_digit = nxt.isascii() and nxt.isdigit() + if prev_is_digit and nxt_is_digit: + out.append(ch) + continue + if ch in (':', ';') and looks_like_math_context(text, i): + out.append(ch) + continue + left = find_strong_neighbor(text, i, -1) + right = find_strong_neighbor(text, i, +1) + if is_chinese_context(left) or is_chinese_context(right): + out.append(mapping[ch]) + continue + if in_ascii_paren: + out.append(ch) + continue + if in_cn_paren or aggressive: + out.append(mapping[ch]) + continue + out.append(ch) + return ''.join(out) + + +def line_is_chinese(line: str) -> bool: + """Heuristic: does this line have enough CJK to call it 'Chinese-flavored'?""" + cjk_count = sum(1 for c in line if is_cjk(c)) + return cjk_count >= 3 + + +def process_text(text: str, aggressive: bool) -> str: + return convert_punct(convert_parens(text, aggressive), aggressive) + + +# Markdown image, markdown link, bare URL, or inline code (in this priority) +OPAQUE_RE = re.compile( + r'!?\[[^\]]*\]\([^\)]+\)' + r'|https?://[^\s\)\]\>]+' + r'|`[^`\n]+`' +) +FENCE_RE = re.compile(r'(```[\s\S]*?```)') + + +def process_segment(segment: str, aggressive: bool) -> str: + """Mask opaque blobs, run conversions, restore (recursively processing + markdown link text).""" + saved = [] + + def stash(m: re.Match) -> str: + saved.append(m.group(0)) + return PLACEHOLDER + + masked = OPAQUE_RE.sub(stash, segment) + converted = process_text(masked, aggressive) + + out = [] + idx = 0 + for ch in converted: + if ch == PLACEHOLDER: + tok = saved[idx] + idx += 1 + m = re.match(r'(!?\[)([^\]]*)(\]\()([^\)]+)(\))', tok) + if m: + inside = process_text(m.group(2), aggressive) + tok = m.group(1) + inside + m.group(3) + m.group(4) + m.group(5) + out.append(tok) + else: + out.append(ch) + return ''.join(out) + + +def process_body_segment(segment: str) -> str: + """Process a non-fenced body segment line by line, choosing aggressive mode + based on whether each logical line is Chinese-flavored.""" + lines = segment.split('\n') + out_lines = [] + for line in lines: + out_lines.append(process_segment(line, aggressive=line_is_chinese(line))) + return '\n'.join(out_lines) + + +def process_yaml_frontmatter(text: str) -> str: + """Convert only quoted string values for description / title / summary keys. + Leaves list/array values like `tags: [...]` alone.""" + def replace_value(m: re.Match) -> str: + prefix, value, suffix = m.group(1), m.group(2), m.group(3) + return prefix + process_segment(value, aggressive=line_is_chinese(value)) + suffix + + return re.sub( + r'^(\s*(?:description|title|summary):\s*")([^"\n]*)(")', + replace_value, + text, + flags=re.MULTILINE, + ) + + +def process_markdown(content: str) -> str: + front = '' + body = content + if content.startswith('---\n') or content.startswith('---\r\n'): + m = re.match(r'(---\r?\n[\s\S]*?\r?\n---\r?\n)', content) + if m: + front = m.group(1) + body = content[m.end():] + + front = process_yaml_frontmatter(front) + + parts = FENCE_RE.split(body) + out = [] + for i, part in enumerate(parts): + if i % 2 == 1: # fenced code block + out.append(part) + else: + out.append(process_body_segment(part)) + return front + ''.join(out) + + +def main() -> None: + changed = [] + for path in sys.argv[1:]: + with open(path, encoding='utf-8', newline='') as f: + content = f.read() + new_content = process_markdown(content) + if new_content != content: + with open(path, 'w', encoding='utf-8', newline='') as f: + f.write(new_content) + changed.append(path) + print(f'updated {path}') + else: + print(f'unchanged {path}') + print(f'\nTotal updated: {len(changed)}') + + +if __name__ == '__main__': + main()