WireGuard 与 wg-easy 速查手册
1. 转发:一个包到达主机后
flowchart TD
A["网卡收到 IP 包"] --> B{"目的 IP 是本机?"}
B -->|"是"| C["交给本机进程<br/>(ping / ssh / 浏览器)"]
B -->|"否"| D{"ip_forward = 1?"}
D -->|"否"| E["丢弃(普通主机默认)"]
D -->|"是"| F["查系统路由表<br/>最长前缀匹配"]
F --> G{"FORWARD 链放行?"}
G -->|"否"| E
G -->|"是"| H["从匹配接口发出<br/>(eth0 / wg0)"]
- 路由表 = 去哪、从哪出(
ip route) ip_forward= 肯不肯帮别人转包- FORWARD 链 = 防火墙放不放转发的包
2. NAT:为什么出口端必须改写源 IP
sequenceDiagram
participant S as 支援PC 10.8.0.3
participant E as 出口机 192.168.80.132
participant T as 比赛机器 192.168.80.10
S->>E: src=10.8.0.3 dst=192.168.80.10
Note over E: POSTROUTING 链 SNAT:<br/>源改写为 192.168.80.132,<br/>conntrack 记录映射
E->>T: src=192.168.80.132
T->>E: 回包 dst=192.168.80.132
Note over E: conntrack 查表:<br/>目的地改回 10.8.0.3
E->>S: dst=10.8.0.3(进 wg 隧道)
不改写源 IP,比赛机器不认识 10.8.0.3,回包石沉大海(回程路由问题)。
SNAT --to-source IP | MASQUERADE | |
|---|---|---|
| 源 IP | 固定指定 | 出口网卡当前 IP(动态) |
| 适用 | IP 恒定(桥接 VM / 静态内网 IP) | IP 浮动(DHCP / 云主机 / WSL2) |
3. WireGuard:AllowedIPs 一个字段两件事
flowchart LR
subgraph OUT ["出方向 = 选路"]
A["目的地命中某 peer 的 AllowedIPs"] --> B["加密发给该 peer"]
end
subgraph IN ["入方向 = 门禁"]
C["从 peer 解密出的包"] --> D{"源 IP 在该 peer<br/>AllowedIPs 内?"}
D -->|"是"| E["放行"]
D -->|"否"| F["静默丢弃"]
end
客户端配置和服务端 wg0.conf 是两张独立的表,各写各的:
flowchart LR
subgraph PC ["支援PC 下载的客户端配置"]
A1["[Peer] 服务器<br/>AllowedIPs =<br/>10.8.0.0/24, 192.168.80.0/24"]
end
subgraph VPSS ["VPS 的 wg0.conf"]
B1["peer(支援PC)<br/>AllowedIPs = 10.8.0.3/32"]
B2["peer(出口机)<br/>AllowedIPs = 10.8.0.2/32,<br/>192.168.80.0/24(挂载网段)"]
end
subgraph EPC ["出口机下载的客户端配置"]
C1["[Peer] 服务器<br/>AllowedIPs = 10.8.0.0/24"]
end
A1 -.加密.-> VPSS
C1 -.加密.-> VPSS
- 系统路由表先于密钥路由:内核先决定包走 wg0,WireGuard 才按 peer AllowedIPs 选加密对象
Table = auto:wg-quick up 时才为 peer 的 AllowedIPs 写系统路由;syncconf只改 peer 表不写路由 → 改完挂载网段必须重启接口PersistentKeepalive = 25:给中间每层 NAT 的 UDP 映射续费
4. 两种出口模型
flowchart LR
A["本地PC-A"] -->|"0.0.0.0/0 全隧道"| V["VPS 原版 wg-easy<br/>MASQUERADE -o eth0"]
B["本地PC-B"] -->|"0.0.0.0/0"| V
V --> I["互联网<br/>所有人的出口 IP = VPS"]
flowchart LR
A["支援PC<br/>10.8.0.3"] -->|"隧道 UDP 51820"| V["VPS<br/>纯转发,不 NAT"]
V -->|"目的 ∈ 192.168.80.0/24<br/>按 peer AllowedIPs"| E["出口机<br/>wg:10.8.0.2<br/>内网:192.168.80.132"]
E -->|"SNAT 源 → .132"| N["比赛内网<br/>192.168.80.0/24"]
| 原版 wg-easy | my-wg-easy(魔改旧版) | 新版 wg-easy | |
|---|---|---|---|
| 出口 | VPS(MASQUERADE) | 指定出口机(SNAT) | 任意,按客户端配 |
| 挂载网段 | 无 | WG_ALLOWED_IPS | 每客户端 Server Allowed IPs |
| 出口端 NAT | 服务端固定 | 硬编码进出口机配置 | 每客户端 Post Up 钩子 |
| 指定出口机 | 无 | 按客户端名 WG_LOCAL_NAME | 显式逐客户端配置 |
| 配置生效 | 重启容器 | 重启容器 | Restart Interface |
5. 场景全景:ping 192.168.80.10 的一生
flowchart TD
S["① 支援PC:路由表 192.168.80.0/24 → wg0,加密"] --> V["② VPS:解密,非本机,转发<br/>需 ip_forward + FORWARD 放行<br/>需系统路由 192.168.80.0/24 → wg0<br/>密钥路由命中出口机 peer,加密"]
V --> E["③ 出口机:解密,非本机,转发<br/>SNAT 源 10.8.0.3 → 192.168.80.132"]
E --> T["④ 比赛机器:只看到 .132 在访问"]
T -->|"⑤ 回包 dst=.132"| E2["⑥ 出口机:conntrack 改回 dst=10.8.0.3<br/>路由 10.8.0.0/24 → wg0,加密"]
E2 --> V2["⑦ VPS:解密,dst=10.8.0.3<br/>/32 最长前缀命中支援PC peer,加密"]
V2 --> S2["⑧ 支援PC:解密,源=192.168.80.10<br/>在自己 AllowedIPs 内 → 放行 ✓"]
6. 新版 wg-easy 比赛内网配置(推荐)
flowchart TD
A["VPS 部署新版 wg-easy,默认配置"] --> B["创建客户端:出口机<br/>按下表配字段"]
B --> C["赛场 Linux 机:<br/>sysctl -w net.ipv4.ip_forward=1<br/>wg-quick up 下载的 conf"]
C --> D["管理后台 Restart Interface<br/>(生成 比赛网段 → wg0 系统路由)"]
D --> E["创建客户端:支援<br/>Allowed IPs 加比赛网段"]
E --> F["分发配置 / 二维码"]
出口机客户端字段:
| 字段 | 值 |
|---|---|
| Allowed IPs | 10.8.0.0/24 |
| Server Allowed IPs | 192.168.80.0/24(比赛网段,可多个) |
| Post Up | iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j SNAT --to-source 192.168.80.132 |
| Post Down | 同上改 -D |
| Persistent Keepalive | 25 |
支援客户端字段:
| 字段 | 值 |
|---|---|
| Allowed IPs | 10.8.0.0/24, 192.168.80.0/24 |
坑:
- 改 Server Allowed IPs 后必须 Restart Interface(syncconf 不写系统路由)
- 出口机须 Linux 且 wg-quick 启动(Windows 原生客户端不执行 PostUp);VM 桥接最佳;WSL2 / Docker 场景 PostUp 改用
-j MASQUERADE - 比赛网段勿与 WG 虚拟网段重叠
- 新客户端默认继承全局 Allowed IPs(
0.0.0.0/0),不改则支援全部流量走 VPS
7. my-wg-easy(旧版)比赛内网配置
| 环境变量 | 示例 | 含义 |
|---|---|---|
WG_LOCAL_NAME | l1aotest | 出口机的客户端名 |
WG_LOCAL_PASS | 192.168.80.132 | 出口机内网 IP(SNAT 目标) |
WG_ALLOWED_IPS | 192.168.80.0/24 | 挂载网段(同时喂客户端路由 + 服务端 peer) |
WG_DEFAULT_ADDRESS | 10.8.0.x | WG 虚拟网段 |
WG_PERSISTENT_KEEPALIVE | 25 | NAT 保活 |
流程:先创建名为 WG_LOCAL_NAME 的客户端 → 重启容器(wg-quick up 才写挂载网段路由)→ 出口机用下载的 conf wg-quick up + 开 ip_forward。
8. 排障:按序检查
flowchart TD
A["ping 不通"] --> B["支援PC:ip route get 目标<br/>走了 wg0?"]
B -->|"否"| B1["AllowedIPs 缺比赛网段"]
B -->|"是"| C["VPS:ip route get 目标<br/>走了 wg0?"]
C -->|"否"| C1["改过挂载网段没重启接口<br/>→ Restart Interface"]
C -->|"是"| D["出口机:tcpdump -ni eth0<br/>有出向包?"]
D -->|"否"| D1["ip_forward 未开 / FORWARD 未放行"]
D -->|"是"| E["回包到出口机却没回支援?<br/>支援 AllowedIPs 缺比赛网段<br/>(被自己 WG 门禁丢弃)"]
| |