WireGuard 哲学篇 引用 Donenfeld(NDSS 2017):Linux 上标准加密隧道是 IPsec + xfrm + 用户态 IKEv2;分层语义正确,却常让正确部署变成多命名空间拼图。本系列从另一端进入——先承认分层,再把它钉到 RFC 4301 的可核对对象上。握手与密钥见后续篇;选型数字见 VPN 工程对比。
一、IPsec 保护什么
RFC 4301 把 IPsec 定义成 IP 层安全架构:为选定的 IP 流量提供机密性、完整性、抗重放与(在策略允许时)有限的流量流机密性。它不是单一协议,而是:
- 安全协议:几乎总是 ESP(RFC 4303);AH(RFC 4302)在现代部署中边缘化。
- 安全关联(SA):一次「用哪套算法与密钥保护哪些方向/选择器」的约定。
- 密钥管理:手工或 IKEv2(RFC 7296)等自动协商。
- 策略:决定哪些包必须/可以/禁止走 IPsec。
关键不变量:策略先于变换。包先被问「要不要保护、如何保护」,再被问「具体 SPI 与密钥是什么」。WireGuard 把这两问塌缩成「公钥 ↔︎ AllowedIPs」;IPsec 坚持拆开。
二、安全关联(SA)
一条 SA 是单向的。双向通信通常需要至少一对 SA(进 / 出)。RFC 4301 用三元组在接收侧标识一条 SA(在给定安全协议下):
- SPI(Security Parameters Index,32-bit)
- 目的 IP 地址
- 安全协议(ESP 或 AH)
发送侧还要知道对端如何查找——通常由 IKE 协商出的 SPI 写入对端 SAD。SA 内还绑定:
- 密码算法与密钥(加密、完整性,或 AEAD 一体)
- 序列号与 anti-replay 窗口状态
- 模式(transport / tunnel)及隧道模式下的外层地址
- 生命周期(时间或字节软/硬限制,常由 IKE 维护)
Child SA 一词来自 IKEv2:相对 IKE SA(保护 IKE 自身)而言,保护用户流量的 ESP/AH SA 称为 Child SA。架构层只关心「用户流量 SA」;命名分工见 握手篇。
三、SPD 与 SAD
flowchart LR
pkt["IP packet"] --> spd["SPD lookup"]
spd -->|"DISCARD"| drop["Drop"]
spd -->|"BYPASS"| fwd["Forward clear"]
spd -->|"PROTECT"| sad["SAD / SA"]
sad --> esp["ESP or AH"]
3.1 SPD(Security Policy Database)
SPD 回答:这个包要不要进 IPsec,以及要用哪类保护。条目由选择器匹配,典型包括:
- 源 / 目的地址范围(前缀)
- 下一层协议(TCP/UDP/ICMP…)及端口(若适用)
- 方向(入 / 出;实现上常拆成 in/out 策略)
- 对 PROTECT:指向所需 SA 的模板(协议、模式、算法约束等)
动作通常三类(RFC 4301 语义):
| 动作 | 含义 |
|---|---|
| DISCARD | 丢弃 |
| BYPASS | 明文转发 |
| PROTECT | 必须按指定 IPsec 应用保护 |
出站:本机发出或转发的包查 SPD;若要求 PROTECT 却找不到可用 SA,实现应触发 IKE 建立 Child SA,或丢弃(取决于策略与实现)。入站:先按 SPI 找到 SA 并完成 ESP/AH 处理,再对照 SPD 检查「解密后的内层头是否符合策略」——防止「用错误 SA 解密出不该进的包」。
3.2 SAD(Security Association Database)
SAD 回答:SPI(等)对应哪把密钥与哪套算法。它是运行时状态库:序列号、重放窗口、密钥材料、模式参数。IKE 守护进程经 PF_KEY 或 netlink(Linux 上多为 XFRM)写入;数据面查找应走快速路径。
工程断层:管理员在 swanctl 里写的是「连接与流量选择器」;内核里看到的是 policy(≈SPD)与 state(≈SAD)。两套视图不同步时,表现为「IKE ESTABLISHED 但业务不通」——运维篇 专写这类故障。
四、传输模式与隧道模式
| 模式 | 保护对象 | 典型场景 |
|---|---|---|
| Transport | 原 IP 包的载荷(上层协议);原 IP 头大体保留在外 | 主机到主机、端到端 |
| Tunnel | 整个原 IP 包作为载荷;外面再套新 IP 头 | 网关到网关、远程接入「虚拟内网」 |
隧道模式是站点互联的默认心智模型:内网
10.1.0.0/16 ↔︎ 10.2.0.0/16
的选择器写在 Child SA 的 TS
里,外层是两个网关公网地址。传输模式少一层封装、MTU
更友好,但要求两端以主机身份直接对话,且中间设备对「原 IP
头仍可见」有不同威胁模型。
WireGuard 只有 L3 隧道语义(虚拟网卡 + AllowedIPs),没有与 transport 模式同构的「保留原外层 IP、只加密载荷」主路径——这是架构分叉,不是功能清单差一项。
五、与 cryptokey routing 的公理对照
| 问题 | IPsec(RFC 4301) | WireGuard |
|---|---|---|
| 身份是什么 | IKE 身份(ID 载荷、证书、PSK)与 SA 分离 | Curve25519 公钥 |
| 谁可以用哪些地址 | SPD/TS 选择器;可与身份多对多 | 公钥绑定 AllowedIPs |
| 算法如何选定 | 提议列表协商(敏捷) | 固定套件(观点化) |
| 管理面对象 | 连接、SA、策略、证书生命周期 | 接口 + peer 表 |
| 代码与审计面 | 用户态 IKE + 内核 xfrm + 算法实现 | 内核模块为主 |
Donenfeld 的批评针对的是工程可部署性,不是否认 SPD/SAD 能表达更细的策略。当合规要求 X.509、当多厂商必须互通、当策略必须按端口/子网精细分割且与路由域解耦时,分层表达力变成优势——代价是调试时必须沿「IKE → policy → state」三条链排查。
六、本文不展开的边界
- IKEv1 的 Main/Aggressive 与多轮相交换:本系列钉 IKEv2;历史仅作对照句。
- 策略语言的全部厂商方言(Cisco crypto map、各云控制台):只保证 RFC 概念与 Linux/strongSwan 映射。
- 性能数字:无本篇实测则不写「隧道比明文慢多少」。
下一篇把控制面钉到 IKEv2 握手 的消息字段。
参考资料
规范
- RFC 4301, Security Architecture for the Internet Protocol.
- RFC 4303, IP Encapsulating Security Payload (ESP)(数据面,下篇起)。
- RFC 7296, Internet Key Exchange Protocol Version 2 (IKEv2).
论文 / 对照
- Donenfeld, J. A. WireGuard: Next Generation Kernel Network Tunnel. NDSS 2017.
站内
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
IPSec / IKEv2 深度系列:从正确分层到 Linux xfrm
作为 WireGuard 系列的对照续作:拆解 RFC 4301 的 SPD/SAD、IKEv2 握手与密钥树、ESP/NAT-T、Linux 6.6 xfrm 与 strongSwan 落盘,并以形式化分析与后量子混合 KE 收束选型边界。
【IPSec】Linux xfrm:从策略查找到加解密
把 RFC 4301 的 SPD/SAD 映射到 Linux 6.6 的 xfrm policy/state:查看出站 xfrm_lookup、入站策略检查与 ip xfrm 观测面,并给出本机 netns 下手工安装 ESP 的对照实验入口。
【WireGuard】设计哲学:故意的分层破坏与密码学观点
WireGuard 不是把 IPSec 写短一点。NDSS 2017 论文把「正确分层」当成复杂度的来源,用 cryptokey routing、固定原语与带外密钥分发换可审计实现。本文钉住这些设计决定及其边界。
【IPSec】ESP、AH 与 NAT-T
数据面几乎总是 ESP:拆开隧道模式封装、AEAD 与 EtM、anti-replay 窗口,以及 NAT 场景下 UDP/4500 封装如何改写外层五元组却保持 SPI 查找语义。