WireGuard — 4000 行代码重写 VPN 的极简主义
待复核WireGuard 是一个运行在 Linux 内核里的 VPN 隧道协议,只用大约 4000 行 C 代码就实现了传统 VPN(OpenVPN 约 10 万行、IPsec/StrongSwan 约 40 万行)的核心功能。日常类比:传统 VPN 像配了几百个按钮的老式仪表盘飞机——功能全但没人敢审计每个开关;WireGuard 像只有方向盘和油门的卡丁车——零件少到谁都能看完,反而更难出事。
它在 2020 年正式合并进 Linux 5.6 内核主线,现在是大多数 Linux 发行版开箱可用的 VPN 方案;macOS / Windows / iOS / Android 则多用用户态实现(wireguard-go),配置格式与内核版一致。
核心设计目标三条:容易正确实现、容易安全审计、高性能。三者互相强化——代码少所以跑得快(缓存友好)、代码少所以审计快、审计快所以能保证正确。
- 代码量少 = 可审计面小。4000 行让形式化验证变得可行(后续确有 CryptoVerif 机械化证明)
- 论文基准下,内核态 + ChaCha20Poly1305 的吞吐与延迟显著优于典型用户态 OpenVPN
- 配置极简:一个接口 = 一个私钥 + 一组 peer 公钥 + 允许的 IP,十几行配置就完事
- 设计哲学影响后来者:Tailscale、Cloudflare WARP、Netbird 等产品都构建在 WireGuard 之上
1. Cryptokey Routing(加密密钥路由)
传统路由是「目标 IP → 下一跳网口」;WireGuard 是「目标 IP → peer 的公钥」。发包查公钥决定用谁的密钥加密;收包从解密成功的密钥反查身份。路由和认证合二为一。类比:信箱上贴着锁,能打开锁就证明邮递员是对的人,不必另查工牌。
2. Noise 握手(固定套件)
用 Noise_IKpsk2(Trevor Perrin 的 Noise 框架的一种模式)做密钥协商。整个握手只要 1-RTT(一来一回)。DH(双方各出一把「半钥匙」合成共享秘密)用 Curve25519;哈希用 BLAKE2s;AEAD(加密同时验真伪)用 ChaCha20Poly1305。密码原语不可协商——没有「选套件」步骤,也就没有降级攻击面。对比 TLS 1.2 常要 2-RTT 还要协商套件,中间人可能伪造「我只支持最弱的」。
3. 内核态 Layer 3 隧道
WireGuard 表现为普通网卡(如 wg0),只处理 Layer 3(IP 包这一层),用 UDP 封装发出。Linux 内核实现的数据路径不经过用户态加解密进程,可直接接 iptables、路由表、network namespace。不用 TCP 封装,是为了避免 TCP-over-TCP 重传叠加(OpenVPN TCP 模式的经典坑)。
场景 1:两台服务器建隧道
Section titled “场景 1:两台服务器建隧道”# 服务器 A(10.0.0.1)——先放行 UDP 51820wg genkey | tee privatekey_a | wg pubkey > publickey_aip link add wg0 type wireguardwg set wg0 private-key ./privatekey_awg set wg0 listen-port 51820wg set wg0 peer <B公钥> \ allowed-ips 10.0.0.2/32 \ endpoint B_IP:51820ip addr add 10.0.0.1/24 dev wg0ip link set wg0 up
# 服务器 B(10.0.0.2)——对称镜像wg genkey | tee privatekey_b | wg pubkey > publickey_bip link add wg0 type wireguardwg set wg0 private-key ./privatekey_bwg set wg0 listen-port 51820wg set wg0 peer <A公钥> \ allowed-ips 10.0.0.1/32 \ endpoint A_IP:51820ip addr add 10.0.0.2/24 dev wg0ip link set wg0 up# 两边防火墙放行 UDP 51820 后:在 A 上 ping 10.0.0.2逐部分解释:
private-key:本机身份(私钥),对应公钥交给对端peer+ 公钥:指定「信谁」allowed-ips:哪些目标 IP 走这条隧道(Cryptokey Routing 的表项)endpoint:对端当前公网地址与端口listen-port:本机收 UDP 的端口(默认常写 51820)
对比 OpenVPN:生成 CA → 签服务器/客户端证书 → 写 .ovpn → 配转发,光证书就够新手折腾一下午。
场景 2:笔记本漫游(Wi-Fi ↔ 4G)
Section titled “场景 2:笔记本漫游(Wi-Fi ↔ 4G)”- 发生了什么:笔记本从 Wi-Fi 切到 4G,公网 IP 变了。
- 协议怎么反应:endpoint 定义为「最后一次收到合法包的来源」;下一包能解密成功就自动更新 endpoint,不必重握手、也不必单独保活会话。
- 你看到什么:上层 SSH / 视频通话不断线——地铁里 Wi-Fi 与蜂窝反复切换时体验最明显。
场景 3:K8s 节点间 overlay 加密
Section titled “场景 3:K8s 节点间 overlay 加密”跨节点 Pod 流量默认不加密。Calico、Cilium 等 CNI 可内置开启 WireGuard:
# Calico 开启 WireGuardapiVersion: projectcalico.org/v3kind: FelixConfigurationmetadata: name: defaultspec: wireguardEnabled: true- 发生了什么:打开开关后,CNI 给每个节点自动配 peer 关系。
- 协议怎么反应:跨节点包自动进入加密隧道,业务 Pod 无感。
- 你看到什么:业务 YAML 几乎不变,节点间多了一层透明加密。
- 没有内建密钥分发:公钥怎么安全送到对端要自己管;大规模部署需 Tailscale 控制面或自建 API,别误以为「配完就安全」。
- 不可协商套件是双刃剑:若 Curve25519 被攻破,不能像 TLS 换套件了事,需要协议版本升级(作者设想 WireGuard v2)。
- IP 与身份绑定:Cryptokey Routing 要求事先配 allowed-ips;想做任意 IP 匿名中继反而不合适。
- NAT 超时:UDP 在企业防火墙上可能被清表项;需 PersistentKeepalive(如每 25 秒),但会暴露流量节奏。
适用 vs 不适用场景
Section titled “适用 vs 不适用场景”适用:
- 服务器 site-to-site、远程办公接入、容器 overlay 加密、对延迟敏感的 VPN
- 点对点或小规模 mesh(peer 通常几十以内可手配);更大规模需外置密钥分发
不适用:
- 要匿名性(用 Tor)——不隐藏双方身份
- 只能走 TCP/HTTP 代理的网络——WireGuard 只用 UDP
- 合规要求可协商特定算法、或需要内建 PKI/证书吊销的企业环境
历史小故事(可跳过)
Section titled “历史小故事(可跳过)”- 审计出身的 Jason Donenfeld 在审 OpenVPN / IPsec 时被代码量与历史包袱震惊——协商逻辑、兼容补丁、状态机分支让安全分析几乎无法穷尽
- 他问:若今天从零设计 VPN,在已有现代密码学原语前提下,最少需要多少代码?答案约 4000 行
- 2017 年论文发表于 NDSS
- Linus Torvalds 在邮件列表称其相对 OpenVPN / IPsec「a work of art」,并希望尽快合入主线
- 2020 年 3 月正式进入 Linux 5.6——从学术论文到全球部署,速度很快
- 极简是一种安全策略:代码越少,攻击面越小,可审计性越高
- 不可协商 ≈ 不可降级:固定套件消掉整类降级攻击;与 TLS 1.3 削减可选套件的方向一致(并行演进,非因果)
- 路由与认证统一:Cryptokey Routing 用一张表同时回答「发给谁」和「信不信」
- 内核数据路径省掉用户态往返:每个包少两次上下文切换,是相对用户态 VPN 的关键性能差来源之一
- WireGuard 白皮书 PDF
- Noise Protocol Framework
- Tailscale 如何在 WireGuard 上建控制面
- CryptoVerif 对 WireGuard 的形式化证明
- Linus 邮件列表评价
- diffie-hellman —— 握手的数学基础,Curve25519 是 ECDH 的一种
- tls-1.3 —— 同向的「砍功能提安全」协议设计,场景不同
- quic —— 同样 UDP、追求低延迟,但解决传输层而非隧道
- cryptoverif-2008 —— WireGuard 握手后来被形式化证明
- bbr-2017 —— 同年网络论文:BBR 管拥塞、WireGuard 管隧道加密
- ebpf —— 常与 WireGuard 配合做流量策略的内核工具
- saltzer-1984-e2e —— 端到端原则:加密放在端点而非中间设备
- chaum-1981-mix —— Mix Network — 用信封套信封让邮局也不知道谁寄给谁
- cryptoverif-2008 —— CryptoVerif — 让计算机直接证密码协议在真实计算模型下安全
- reed-onion-routing-1998 —— Onion Routing 1998 — Tor 前身把匿名连接做成网络积木
- openwrt —— OpenWrt — 把家用路由器变成 Linux 服务器
- shadowsocks-libev —— Shadowsocks-libev — 嵌入式设备上的轻量 SOCKS5 加密代理
- wireguard-go —— WireGuard-Go — WireGuard VPN 的 Go 用户态实现