# 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 为什么有时能打通、有时不行
- 成功率高：全锥形、受限锥形 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`

```ini
[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`

```ini
[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`

```ini
[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`

```ini
[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`

```ini
[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`

```ini
[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`

```ini
[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`

```ini
[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`

```ini
[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`

```ini
[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`

```ini
[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`

```ini
[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`

```ini
[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 故障会断链；吞吐受中间节点限制
