土法炼钢兴趣小组的算法知识备份

【WireGuard】设计哲学:故意的分层破坏与密码学观点

文章导航

分类入口
networksecurity
标签入口
#wireguard#design-philosophy#cryptokey-routing#ipsec#noise-protocol#ndss

目录

把 WireGuard 理解成「更快的 OpenVPN」或「配置更简单的 IPSec」,会漏掉真正的设计主张。Jason A. Donenfeld 在 NDSS 2017 论文里写得很直白:Linux 上标准的加密隧道方案是 IPsec + xfrm + 用户态 IKEv2;分层在语义上正确,但正确分层把正确部署变成了几乎不可完成的任务。WireGuard 从「有缺陷的分层破坏」出发,再用密码学与系统手段把洞补上——这是哲学,不是实现细节。

本文只谈立场与公理。握手字段见 协议原理;内核路径见 代码篇。选型数字与 OpenVPN 对照见 VPN 工程对比

一、问题从哪来:正确分层的代价

IPSec 把三件事拆开:

  1. 密钥交换(通常 IKEv2,RFC 7296 及大量扩展)
  2. 变换 / SA(内核 xfrm:SPD 选策略,SAD 绑密钥与算法)
  3. 接口与防火墙语义(与普通网卡规则不完全同构)

Donenfeld(NDSS 2017, §I)承认:密钥交换与传输加密分离、变换层与接口分离,在网络与安全教科书里都站得住。问题在工程:管理员要在多个命名空间里保持一致;防火墙对「经 IPsec 的包」有另一套标签;出了问题很难判断是 IKE、SPD 还是 SAD 哪一层与预期不一致。

OpenVPN 站在另一端:用户态 TUN/TAP + TLS。接口模型更接近普通网卡,但把 ASN.1/X.509 与庞大 TLS 状态机留在长期守护进程里;论文指出内核里塞 TLS/X.509 解析器历史上出过严重漏洞(文中举例 CVE-2008-1673、CVE-2016-2053),因此 OpenVPN 留在用户态是合理的——代价是多次内核–用户拷贝与「看起来很有状态」的运维面。

WireGuard 的目标陈述(论文 Abstract)可以压缩成一句话:用更少的代码、更固定的密码学、更接近普通网卡的管理面,替代多数场景下的 IPsec 与 OpenVPN。

二、公理一:安全隧道的基本原理是公钥 ↔︎ IP 绑定

论文 §II 提出 cryptokey routing:peer 的唯一身份是 32 字节 Curve25519 公钥;每个公钥绑定一组 Allowed IPs。

出方向:内层目的 IP → 查表选公钥 → 用该 peer 的会话密钥加密。
入方向:解密认证通过后,内层源 IP 必须仍落在同一公钥的 Allowed IPs 上,否则丢弃。

这不是「路由功能外挂了一个 VPN」,而是主张:安全隧道的基本不变量就是「谁可以用哪些源 IP」。SPD/SAD 的两层表在 WireGuard 里塌缩成一张表。代价也很清楚:它要求协议是纯 L3——没有「源 IP」的 L2 帧无法做同样的绑定,因此 WireGuard 拒绝做通用 L2 VPN(论文 §I、§II)。

flowchart LR
  subgraph IPSec[IPSec Layering]
    IKE[IKEv2 Daemon]
    SPD[SPD]
    SAD[SAD]
    XFRM[xfrm Transform]
  end
  subgraph WG[WireGuard Model]
    CK["Public Key + AllowedIPs"]
    IF["wg0 net_device"]
  end
  IKE --> SPD --> SAD --> XFRM
  CK --> IF

论文自己把这叫做对「学术完美分层」的背离,然后用 roaming、静默丢弃、cookie DoS 机制等补工程问题。读后续协议与代码时,应把 cryptokey routing 当成公理,而不是「配置语法糖」。

三、公理二:管理面看起来无状态

配置完成后,密钥交换、断线重连、endpoint 发现应对管理员透明:wg0 像一张普通网卡,用 ip(8) 配地址与路由,用普通防火墙规则约束从该接口进来的包——并保证这些包已经过认证加密(论文 §I)。

这推出几条工程推论:

「无状态」是对外观的描述,不是实现里没有状态机。内核里有 timer、keypair 轮换与队列;哲学要求是这些状态不进入管理员的日常心智模型

四、公理三:密钥分发不在这一层解决

WireGuard 的静态公钥交换刻意学 OpenSSH:带外完成,协议不绑定 X.509、CRL、OCSP(论文 §I)。公钥 32 字节、Base64 约 44 字符,方便邮件、配置管理、密钥分发系统投递。

这不是「没有身份」,而是身份 = 公钥,信任锚放在运维流程里。合规若强制要求证书链与撤销基础设施,哲学上就不匹配——应回到 IKEv2 或在 WireGuard 之外另建身份平面(见 深度篇 与零信任系列)。

可选预共享对称密钥(PSK)也不改变这条公理:PSK 是对 ECDH 的额外混合,用于「极偏执」的量子威胁模型(§V-B),不是 PKI。

五、公理四:密码学观点(cryptographically opinionated)

论文 §I 写明:WireGuard 故意没有 cipher 与协议敏捷性。原语固定为:

角色 选择 规范锚点
ECDH Curve25519 Bernstein
AEAD ChaCha20-Poly1305 RFC 7539
Hash / KDF BLAKE2s + HKDF RFC 7693 / RFC 5869
握手框架 Noise IK(及 PSK 变体) Noise Protocol Framework

立场是:TLS 历史上大量漏洞与「可协商」相关;与其保留降级与组合爆炸,不如原语出洞时全员升级协议版本。netdev 邮件列表里对「失败日怎么办」的争论,以及「用 message type / 版本严格演进」的回应,放到 深度篇

握手模式选 Noise IK:发起方预先知道响应方静态公钥——这与 VPN「配好对端公钥再通信」的运维模型同构,也与「第一条消息即可认证、尽量不分配未认证状态」一致。

六、可审计性是一等目标

论文收束:Linux 实现目标是少于约 4000 行,以便审计与验证。主线合并后代码量有增长,但仍比 IPsec/IKE 用户态+内核总和小一个数量级(本站 内部实现文 对 2026 主线 .c 约 5000 行的统计)。

「少行数」本身不是安全证明。它服务的是哲学目标:一个人或一个小团队能读完实现;协议固定后才谈得上 Tamarin / 计算模型分析(见深度篇)。若为了功能把协商机与证书解析加回来,行数与攻击面会一起回来——那是另一款产品。

七、这套哲学明确不覆盖什么

下列边界来自论文主张与后续工程现实,不是贬义清单:

需求 为何不匹配
L2 延伸 / VLAN 广播域 无稳定「源 IP ↔︎ 公钥」语义
运行时算法套件协商 与 opinionated crypto 冲突
内核内置证书 PKI 与 SSH 式带外身份冲突;也回避 ASN.1 解析面
「拨入即信任」的大平面 VPN 不加分段 cryptokey routing 只保证接口上源 IP 可信,不替你做应用授权

WireGuard 解决的是:在不可信 IP 网上,为已交换公钥的 peer 提供认证、加密、前向保密的 L3 管道,并让管道看起来像网卡。 身份治理、设备姿态、应用层授权属于别的平面。

八、小结

WireGuard 的哲学可以记成四条:

  1. 公钥即 peer,AllowedIPs 即策略 —— cryptokey routing。
  2. 管理面无状态外观 —— 握手与漫游藏进内核。
  3. 密钥分发带外 —— 不造 PKI。
  4. 密码学固定、版本演进 —— 不造协商机。

下篇从这些公理推出具体消息:Noise IKpsk2 的字段、四次 DH 的属性贡献,以及为何安全数据路径是 1.5 RTT。

参考资料

论文 / 规范

相关站内文

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-07-19 · network / security

WireGuard 深度系列:从设计哲学到内核实现

从 Donenfeld NDSS 2017 的设计哲学出发,拆解 Noise IKpsk2、内核数据路径、运维实践与形式化验证争论——把 WireGuard 从「好用的 VPN」讲成可核对的协议与系统。

2026-06-20 · network

【网络工程】WireGuard 内部实现:Cryptokey Routing、Noise IK 握手与内核数据路径

WireGuard 用不到 4000 行内核代码替代了 IPSec/IKE 数十万行的协议栈——这不是少写功能,而是用固定密码学原语、固定握手模式和 cryptokey routing 这三个设计决定,换掉了证书体系、协商机和 SPD/SAD 分离。本文钻进源码和协议握手过程,逐层拆解 cryptokey routing 的双向执行、Noise IKpsk2 的 1.5 RTT 握手(含四次 ECDH 的安全属性贡献)、内核多核队列架构、timer 状态机、cookie DoS 防御和三密钥对轮换。


By .