#IP / Port 变化时,连接不需要重建、不中断、甚至不需要“感知恢复
这是 WireGuard 最“魔法”的地方之一:
IP / Port 变化时,连接不需要重建、不中断、甚至不需要“感知恢复”。
结论先行一句话:
WireGuard 根本不把“连接”绑定在 IP/Port 上,而是绑定在密钥身份上。
下面我从 机制 → 数据路径 → 时序 → 边界条件 四个层次,把它彻底拆开。
一、WireGuard 的“连接”到底是什么?
在 WireGuard 里:
| 传统 VPN | WireGuard |
|---|---|
| 连接 = TCP/UDP 会话 | 连接 = 公钥身份 + 会话密钥 |
| IP/Port 是身份的一部分 | IP/Port 只是“最近一次可达路径” |
| 断链要重连 | 路径变了自动学习 |
✅ IP/Port 不是连接的锚点
真正的锚点是:
Peer Public Key → Session (Noise IK)
二、核心设计:Endpoint 是“可学习”的
在 struct wg_peer 里,有一个非常关键的字段:
struct endpoint endpoint;
这个 endpoint:
- ✅ 不是配置死的
- ✅ 可以被运行时更新
- ✅ 每次收到合法数据包都可能刷新
三、IP/Port 变化时发生了什么?(完整时序)
我们假设一个最常见的场景:
手机从 Wi‑Fi → 4G
IP 变了,端口也变了
🟢 第 1 步:客户端发送任意 WireGuard 数据包
- 可能是:
- keepalive
- 数据包
- rekey 包
- 使用 已有会话密钥 加密
- UDP 源 IP / Port 已经变了
🟢 第 2 步:服务端收到 UDP 包
服务端做的第一件事不是:
❌ “你 IP 变了,拒绝”
而是:
✅ 先尝试解密
流程是:
UDP 包 →
解析 WireGuard 消息类型 →
用所有 peer 的 key 尝试匹配 →
找到能成功解密的 peer
⚠️ 这里的查找是 基于 key,而不是 IP
🟢 第 3 步:认证成功 → 更新 endpoint
一旦解密 + 认证成功:
peer->endpoint = skb->src_ip:src_port;
✅ endpoint 被原子性更新
这一步叫:
Endpoint Roaming
而且是:
- 无日志
- 无状态切换
- 无 reconnect
🟢 第 4 步:后续所有包都走新路径
之后服务端发包:
peer->endpoint → 新 IP/Port
旧路径自然失效。
四、为什么这样做是安全的?
关键在于这条铁律:
只有能通过 Noise 认证的包,才有资格更新 endpoint
也就是说:
- ❌ 伪造源 IP 不行(解不开)
- ❌ 猜端口不行
- ❌ 重放旧包不行(counter / replay window)
五、代码层面的“无感知”来源
1️⃣ 查找 peer 不靠 IP
核心路径:
wg_receive_handshake_packet()
wg_receive_data_packet()
它们最终都是:
→ 根据 key 找 peer
→ 而不是根据 src IP
2️⃣ endpoint 更新是“副作用”
你可以理解为:
“如果你能证明你是谁,
那你现在从哪来我就信”
所以 endpoint 更新只是:
- 一次
memcpy - 一次 RCU-safe 更新
- 不影响 fast path
3️⃣ Keepalive 的真实意义
很多人误解 keepalive 是“保活连接”。
实际上它是:
NAT 穿透 + endpoint 探测包
- 保证 NAT 映射不消失
- 确保对端知道“我现在在哪”
六、为什么 TCP VPN 做不到?
因为 TCP:
- ✅ IP/Port 是连接五元组的一部分
- ❌ IP 变了 = 连接必断
- ❌ NAT 变化 = RST / timeout
WireGuard:
- ✅ UDP 无连接
- ✅ 自己在加密层维护“逻辑会话”
- ✅ 会话 ≠ 传输路径
七、几个非常重要的边界条件(容易踩坑)
⚠️ 1. 双方都在 NAT 后面?
- ❌ 无法首次建立连接
- ✅ 但一旦建立,双方 roaming 都没问题
- 解决方案:中继 / 固定一端公网
⚠️ 2. 长时间完全静默?
- NAT 映射过期
- 下一包可能丢
- ✅ PersistentKeepalive 就是为这个准备的
⚠️ 3. 同一 peer 同时从两个 IP 发包?
- WireGuard 最后一个成功认证的 endpoint 生效
- 不是负载均衡
- 是“单活”
八、一句话总结“无感知恢复”的本质
WireGuard 把“身份”和“路径”彻底解耦了。
- 身份:公钥(不可伪造)
- 会话:Noise state
- 路径:随时可变、随时学习
所以:
IP/Port 变化不是异常,只是一次新的事实被观察到。