WireGuard 组网与 NAT 打洞知识总结
1. 什么是“打洞”(NAT Hole Punching)
打洞的目标:让两个都在 NAT 后面的节点建立直连(常见于 UDP)。
1.1 基本原理(UDP)
- 节点 A、B 先连接一个公网可达的协调节点 C。
- C 记录 A/B 的公网出口地址(IP:Port)并互相下发。
- A、B 同时向对方公网地址发 UDP 包。
- NAT 看到“内网先发起外联”,会临时放行回包,形成“洞”。
- 若两边 NAT 策略允许,A↔B 直连建立。
1.2 为什么有时能打通、有时不行
- 成功率高:全锥形、受限锥形 NAT
- 成功率低:对称 NAT、双重 NAT、运营商 CGNAT
- 失败时通常需要中继(Relay)
1.3 在 WireGuard 中的关系
- WireGuard 使用 UDP,适合打洞。
- WireGuard 本身不负责“协调发现”,通常需要外部控制面。
- 常用参数:
PersistentKeepalive = 25(保持 NAT 映射)
2. 三种常见组网模式对比
| 模式 | 结构 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| Hub-and-Spoke | 多台连一台 Hub | 简单、集中管理 | Hub 成为瓶颈/单点 | 中小规模、中心化管理 |
| 链式 A→B→C | 逐跳转发 | 可达性接力、分层控制 | 时延上升、中间节点关键 | 多层网络、不可直连环境 |
| 全互联 Mesh | 两两直连 | 延迟低、路径短 | 配置复杂、节点多时爆炸 | 小规模高性能互联 |
3. 示例配置(可直接改造)
说明:以下
PrivateKey/PublicKey/Endpoint都是占位符。
转发节点(Hub、链路中的中间节点)需开启 IP 转发。
3.1 Hub-and-Spoke(Hub + A + B)
Hub /etc/wireguard/wg0.conf
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = <HUB_PRIVATE_KEY>
[Peer]
PublicKey = <A_PUBLIC_KEY>
AllowedIPs = 10.10.0.2/32
[Peer]
PublicKey = <B_PUBLIC_KEY>
AllowedIPs = 10.10.0.3/32
A wg0.conf
[Interface]
Address = 10.10.0.2/24
PrivateKey = <A_PRIVATE_KEY>
[Peer]
PublicKey = <HUB_PUBLIC_KEY>
Endpoint = hub.example.com:51820
AllowedIPs = 10.10.0.0/24
PersistentKeepalive = 25
B wg0.conf
[Interface]
Address = 10.10.0.3/24
PrivateKey = <B_PRIVATE_KEY>
[Peer]
PublicKey = <HUB_PUBLIC_KEY>
Endpoint = hub.example.com:51820
AllowedIPs = 10.10.0.0/24
PersistentKeepalive = 25
3.2 链式 A→B→C(A/C 不直连)
B(中继)wg0.conf
[Interface]
Address = 10.20.0.2/24
ListenPort = 51820
PrivateKey = <B_PRIVATE_KEY>
[Peer]
PublicKey = <A_PUBLIC_KEY>
AllowedIPs = 10.20.0.1/32
[Peer]
PublicKey = <C_PUBLIC_KEY>
AllowedIPs = 10.20.0.3/32
A wg0.conf
[Interface]
Address = 10.20.0.1/24
PrivateKey = <A_PRIVATE_KEY>
[Peer]
PublicKey = <B_PUBLIC_KEY>
Endpoint = b.example.com:51820
AllowedIPs = 10.20.0.2/32, 10.20.0.3/32
PersistentKeepalive = 25
C wg0.conf
[Interface]
Address = 10.20.0.3/24
PrivateKey = <C_PRIVATE_KEY>
[Peer]
PublicKey = <B_PUBLIC_KEY>
Endpoint = b.example.com:51820
AllowedIPs = 10.20.0.2/32, 10.20.0.1/32
PersistentKeepalive = 25
3.3 全互联 Mesh(A/B/C 两两直连)
A wg0.conf
[Interface]
Address = 10.30.0.1/24
ListenPort = 51820
PrivateKey = <A_PRIVATE_KEY>
[Peer]
PublicKey = <B_PUBLIC_KEY>
Endpoint = b.example.com:51820
AllowedIPs = 10.30.0.2/32
[Peer]
PublicKey = <C_PUBLIC_KEY>
Endpoint = c.example.com:51820
AllowedIPs = 10.30.0.3/32
B wg0.conf
[Interface]
Address = 10.30.0.2/24
ListenPort = 51820
PrivateKey = <B_PRIVATE_KEY>
[Peer]
PublicKey = <A_PUBLIC_KEY>
Endpoint = a.example.com:51820
AllowedIPs = 10.30.0.1/32
[Peer]
PublicKey = <C_PUBLIC_KEY>
Endpoint = c.example.com:51820
AllowedIPs = 10.30.0.3/32
C wg0.conf
[Interface]
Address = 10.30.0.3/24
ListenPort = 51820
PrivateKey = <C_PRIVATE_KEY>
[Peer]
PublicKey = <A_PUBLIC_KEY>
Endpoint = a.example.com:51820
AllowedIPs = 10.30.0.1/32
[Peer]
PublicKey = <B_PUBLIC_KEY>
Endpoint = b.example.com:51820
AllowedIPs = 10.30.0.2/32
4. 扩展链式:B 连 A、C 连 B、D 连 C(四级链)
这个结构有价值,属于可达性接力。
例如只有 A 公网可达,D 通过 C→B 才能间接到达 A。
A wg0.conf
[Interface]
Address = 10.40.0.1/24
ListenPort = 51820
PrivateKey = <A_PRIVATE_KEY>
[Peer]
PublicKey = <B_PUBLIC_KEY>
AllowedIPs = 10.40.0.2/32, 10.40.0.3/32, 10.40.0.4/32
B wg0.con
[Interface]
Address = 10.40.0.2/24
ListenPort = 51820
PrivateKey = <B_PRIVATE_KEY>
[Peer]
PublicKey = <A_PUBLIC_KEY>
Endpoint = a.example.com:51820
AllowedIPs = 10.40.0.1/32
PersistentKeepalive = 25
[Peer]
PublicKey = <C_PUBLIC_KEY>
AllowedIPs = 10.40.0.3/32, 10.40.0.4/32
C wg0.conf
[Interface]
Address = 10.40.0.3/24
ListenPort = 51820
PrivateKey = <C_PRIVATE_KEY>
[Peer]
PublicKey = <B_PUBLIC_KEY>
Endpoint = b.example.com:51820
AllowedIPs = 10.40.0.1/32, 10.40.0.2/32
PersistentKeepalive = 25
[Peer]
PublicKey = <D_PUBLIC_KEY>
AllowedIPs = 10.40.0.4/32
D wg0.conf
[Interface]
Address = 10.40.0.4/24
PrivateKey = <D_PRIVATE_KEY>
[Peer]
PublicKey = <C_PUBLIC_KEY>
Endpoint = c.example.com:51820
AllowedIPs = 10.40.0.1/32, 10.40.0.2/32, 10.40.0.3/32
PersistentKeepalive = 25
该模式优缺点
- 优点:解决不可直连、支持分层控制
- 缺点:多跳增加时延;B/C 故障会断链;吞吐受中间节点限制