--- tags: [计算机网络, WireGuard, VPN, ChaCha20, Curve25519, OpenVPN, IPsec] create time: 2026-05-18 05:35 --- # WireGuard VPN 原理与实践 ## 概述 WireGuard 是一个极简的 VPN 协议,代码量不到 OpenVPN 的 1/10、IPsec 的 1/25。它凭借极低的延迟和超高的吞吐量,正在成为新一代标准 VPN 方案——甚至已合入 Linux 内核(≥ 5.6)。 ## 为什么比 OpenVPN / IPsec 快? ```mermaid flowchart LR IPsec["IPsec\n• IKEv2 密钥交换 (多轮 RTT)\n• ESP/AH 扩展头链\n• 用户态+内核态来回跳转\n• ~10-20 种 cipher suite 协商"] WG["WireGuard\n• Curve25519 密钥交换 (单次)\n• ChaCha20-Poly1305 AEAD\n• 纯内核态实现 (netlink API)\n• 仅 4 种密码学原语"] style IPsec fill:#DDA0DD,color:#000 style WG fill:#98FB98,color:#000 ``` ### 性能对比实测数据 | 指标 | WireGuard | OpenVPN (UDP) | IPsec | |------|-----------|--------------|-------| | **吞吐量** | ~9.5 Gbps | ~1.5 Gbps | ~3.0 Gbps | | **CPU 占用 (Gbps)** | 0.8% | 12.5% | 3.2% | | **握手延迟** | < 1ms | 50-200ms | 100-300ms | | **代码行数** | ~4,000 LoC | ~50,000 LoC | ~100,000 LoC | | **配置复杂度** | 极简 (INI 格式) | 中等 | 复杂 | | **NAT 遍历** | 原生支持 | 需要辅助 (UDP encapsulation) | 复杂 | | **移动性** | 支持 (PersistentKeepalive + endpoint change) | 部分支持 | 有限支持 | > [!tip] 代码行数少 = 更少的 bug = 更高的安全性 > > 审计 ~4000 行 C 代码的成本远低于审计 ~50000 行。而且每少一行代码就少一个潜在的漏洞入口。 ## WireGuard 的密码学基础 ``` WireGuard 仅使用 4 种经过严格审查的密码学原语: ─────────────────────────────────────────────── 1. Curve25519 — ECDH 密钥交换 (x25519) 2. ChaCha20 — 对称加密 (AES 替代) 3. Poly1305 — MAC / AEAD 认证 4. SHA-512 — 哈希函数 没有: RSA, ECC(除Curve25519外), CBC, HMAC, DRBG... → 选择极少 → 无协商 → 更快更简单 ``` ### 三重加密手风琴 (Triple Handshake) ```mermaid sequenceDiagram participant A as Peer A participant B as Peer B Note over A,B: 1. A → B: 主动握手 (A 发起) A->>B: {Ephemeral Key A} 用 B's Static Key 加密 B->>A: {Ephemeral Key B} 用 A's Ephemeral Key + B's Static Key 加密 A->>B: {Empty} 用 A's Ephemeral Key + B's Ephemeral Key 加密 Note over A,B: ✅ 三方加密完成, 会话密钥建立 Note over A,B: 2. B → A: 响应式重握手 (B 轮换密钥) B->>A: {Ephemeral Key B'} 用 A's Static Key 加密 A->>B: {Ephemeral Key A'} 用 B's Ephemeral Key + A's Static Key 加密 B->>A: {Empty} 用 B's Ephemeral Key + A's Ephemeral Key 加密 Note over A,B: ✅ 新会话密钥, 前向保密保证 ``` > [!question] 什么是前向保密 (Forward Secrecy)? > 即使长期密钥(Static Key)未来被泄露,也无法解密过去的通信——因为每次会话都使用了临时的 Ephemeral Key。三重手风琴保证了每一轮的临时密钥都在下一轮中被"销毁"。 ## WireGuard 配置详解 ### server.conf ```ini [Interface] Address = 10.0.0.1/24 # WireGuard 虚拟网卡 IP ListenPort = 51820 # UDP 监听端口 PrivateKey = # 私钥 (安全保存!) PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE # NAT 转发 PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE [Peer] # 客户端 1 PublicKey = AllowedIPs = 10.0.0.2/32 # 只允许这个 IP 通过这个 peer PersistentKeepalive = 25 # 每 25s 发一次 keepalive (穿透 NAT) [Peer] # 客户端 2 PublicKey = AllowedIPs = 10.0.0.3/32 PersistentKeepalive = 25 ``` ### client.conf ```ini [Interface] Address = 10.0.0.2/24 # 客户端自己的虚拟 IP PrivateKey = # 客户端私钥 # DNS 解析通过隧道走 VPN DNS = 10.0.0.1 [Peer] PublicKey = # ⚠️ 注意方向: 客户端存服务端的公钥 Endpoint = vpn.example.com:51820 # 服务器地址 AllowedIPs = 0.0.0.0/0 # 所有流量走 VPN (全隧模式) # AllowedIPs = 10.0.0.0/24 # 仅内网流量走 VPN (-split tunneling) PersistentKeepalive = 25 ``` ### 一键生成密钥对 ```bash # 生成服务器密钥对 $ wg genkey | tee server-private.key | wg pubkey > server-public.key # 生成客户端密钥对 (可重复 N 次) $ wg genkey | tee client1-private.key | wg pubkey > client1-public.key $ wg genkey | tee client2-private.key | wg pubkey > client2-public.key # 生成 QR Code (方便手机扫码连接) $ qrencode -t UTF8 <(cat <(echo "[Interface]"); echo "PrivateKey=$(cat client1-private.key)"; echo "[Peer]"; echo "PublicKey=$(cat server-public.key)"; echo "AllowedIPs=0.0.0.0/0"; echo "Endpoint=vpn.example.com:51820"; echo "PersistentKeepalive=25") ``` ### 日常运维命令 ```bash # 启动 WireGuard $ sudo wg-quick up wg0 $ sudo systemctl enable --now wg-quick@wg0 # 开机自启 # 查看状态 $ wg show interface: wg0 public key: abc123def456... private key: (hidden) listening port: 51820 peer: xyz789ghi012... endpoint: 203.0.113.5:45678 allowed ips: 10.0.0.2/32 latest handshake: 3 seconds ago ← 3 秒前还在握手! 连接活跃 transfer: 1.23 GiB received, 890 MiB sent # 动态添加/移除 peer (不需要重启!) $ wg set wg0 peer allowed-ips 10.0.0.4/32 $ wg remove wg0 peer # 导入导出配置 $ wg syncconf wg0 <(wg-quick strip wg0) ``` ## WireGuard 的限制与注意事项 ``` ⚠️ WireGuard 不适合的场景: ───────────────────────────────── • 需要传统用户认证 (PAP/CHAP/LDAP) → WireGuard 只认密钥 • 细粒度 per-user 带宽控制 → 需配合 tc (traffic control) • 大规模动态节点 (千级以上) → 管理 1000 个 peer 的 AllowedIPs 很痛苦 • 与现有 IPsec 设备互通 → WireGuard 不能做 IPsec gateway ✅ WireGuard 非常适合: ───────────────────────────────── • 个人/小团队私有 VPN • 云服务器到 IDC 的专线 • IoT 设备远程管理 • Kubernetes 集群跨 AZ 通信 ``` ## 关联笔记 - [[hhs/NETWORK/eBPF与ServiceMesh]] — eBPF 可用于监控 WireGuard 接口的流量 - [[hhs/NETWORK/SDNSRv6与网络编程最佳实践]] — SDN + SRv6 是更宏大的网络可编程愿景 - [[hhs/NETWORK/IPv6地址与扩展头部]] — IPv6 SLAAC 自动配置与 WireGuard 的静态分配对比