WireGuard 组网与 NAT 打洞知识总结

1. 什么是“打洞”(NAT Hole Punching)

打洞的目标:让两个都在 NAT 后面的节点建立直连(常见于 UDP)。

1.1 基本原理(UDP)

  1. 节点 A、B 先连接一个公网可达的协调节点 C。
  2. C 记录 A/B 的公网出口地址(IP:Port)并互相下发。
  3. A、B 同时向对方公网地址发 UDP 包。
  4. NAT 看到“内网先发起外联”,会临时放行回包,形成“洞”。
  5. 若两边 NAT 策略允许,A↔B 直连建立。

1.2 为什么有时能打通、有时不行

1.3 在 WireGuard 中的关系


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

该模式优缺点