我的 WireGuard 多站点互联实践
2025-10-13

家里有两个地方都有网络设备,加上经常需要在外面访问家里的 NAS 和虚拟机,一直想搭个 VPN 把这些网络连起来。试过 OpenVPN、IPSec 之后,最终选了 WireGuard:配置文件短、性能好、内核态运行,整体体验比其他方案好不少。

这篇文章记录了我从规划到部署的完整过程,包括踩过的坑和一些实际经验。

需求分析和方案选择

先说说我的具体需求:

方案对比的时候考虑过几种:

方案优点缺点
OpenVPN成熟稳定,穿透性好性能差,配置复杂,用户态运行
IPSec/IKEv2标准协议,系统原生支持配置非常复杂,排错困难
Tailscale开箱即用,NAT 穿透依赖第三方,免费版有设备限制
WireGuard内核态,性能好,配置简洁需要一台有公网 IP 的服务器

最终选了 WireGuard + Hub-and-Spoke 架构。用一台阿里云 ECS(有公网 IP)做中转节点,所有设备都连到这台服务器,由它负责转发流量。架构简单,也方便管理。

网络拓扑

下面这张图就是我现在的网络结构:

flowchart TD
    Internet[Public Internet]

    subgraph Cloud[Alibaba Cloud ECS Relay Server]
        ECS[<strong>ECS Relay Server</strong><br>Public IP: 203.0.113.1<br>VPN IP: 192.168.151.1/24<br>Port: 24356/UDP]
    end

    subgraph HomeA[Home Network A]
        OP1[<strong>OpenWrt Gateway A</strong><br>LAN: 192.168.2.1/24<br>VPN: 192.168.151.2/24]
        OtherA[Other Devices<br>192.168.2.0/24]
    end

    subgraph HomeB[Home Network B]
        OP2[<strong>OpenWrt Gateway B</strong><br>LAN: 192.168.4.1/24<br>VPN: 192.168.151.3/24]
        OtherB[Other Devices<br>192.168.4.0/24]
    end

    subgraph Mobile[Mobile Devices]
        MAC[<strong>MacBook</strong><br>VPN IP: 192.168.151.4/24]
        IPH[<strong>iPhone</strong><br>VPN IP: 192.168.151.5/24]
    end

    Internet -- Internet Connection --> ECS

    ECS -- WireGuard Tunnel<br>PersistentKeepalive: 25 --> OP1
    ECS -- WireGuard Tunnel<br>PersistentKeepalive: 25 --> OP2
    MAC -- WireGuard Tunnel<br>PersistentKeepalive: 25 --> ECS
    IPH -- WireGuard Tunnel<br>PersistentKeepalive: 25 --> ECS

    OP1 -- LAN Network --> OtherA
    OP2 -- LAN Network --> OtherB

关键点:

WireGuard 基本原理

WireGuard 的核心是公钥加密体系,每个节点持有一对密钥(私钥 + 公钥)。双方交换公钥后即可建立加密隧道,不需要像 OpenVPN 那样搞证书颁发机构(CA)。

下面是连接建立的过程:

sequenceDiagram
    participant S as 服务器<br/>(私钥S_priv, 公钥S_pub)
    participant C as 客户端<br/>(私钥C_priv, 公钥C_pub)

    Note over S,C: 配置阶段:交换公钥
    S->>S: 配置文件中添加C_pub
    C->>C: 配置文件中添加S_pub

    Note over S,C: 握手建立过程
    C->>S: 1. 发送握手初始化包<br/>(用S_pub加密,用C_priv签名)
    S->>S: 2. 用S_priv解密,用C_pub验证签名
    S->>C: 3. 发送握手响应包<br/>(用C_pub加密,用S_priv签名)
    C->>C: 4. 用C_priv解密,用S_pub验证签名

    Note over S,C: 双方协商会话密钥
    Note over S,C: 5. 握手完成,生成共享密钥

    Note over S,C: 数据传输
    S->>C: 发送加密数据
    C->>S: 发送加密数据

几个值得注意的技术细节:

实际搭建过程

1. 安装 WireGuard

各平台的安装都很直观:

# Ubuntu / Debian
sudo apt update && sudo apt install wireguard

# OpenWrt(通过 opkg)
opkg update && opkg install wireguard-tools kmod-wireguard luci-proto-wireguard

手机和电脑直接在应用商店搜 WireGuard 官方 App 即可。

2. 生成密钥对

为每个节点生成独立的密钥对:

# 设置安全的文件权限
umask 077

# 生成密钥对并输出(一次性命令,不留文件)
wg genkey | tee /dev/stderr | wg pubkey
# 第一行输出是私钥,第二行是公钥

也可以分步操作,更清晰一些:

# 生成私钥
wg genkey > server_private.key

# 从私钥推导公钥
wg pubkey < server_private.key > server_public.key

# 查看密钥(注意保管私钥!)
cat server_private.key
cat server_public.key

需要为 ECS 服务器、两台 OpenWrt 路由器、MacBook、iPhone 各生成一对。然后交叉配置公钥:每个节点的配置里要包含所有它要通信的对端的公钥。

3. 理解 AllowedIPs

这是 WireGuard 配置中最容易出错的地方,值得单独说一下。AllowedIPs 同时充当两个角色:

举个例子,在 ECS 服务器上给家庭网络 A 的路由器配置 AllowedIPs = 192.168.151.2/32, 192.168.2.0/24,意思是:

  1. 发往 192.168.151.2192.168.2.0/24 的流量走这条隧道
  2. 从这条隧道进来的数据包,源 IP 必须是 192.168.151.2192.168.2.0/24 网段

4. 中心节点配置(ECS 服务器)

这是整个架构的核心,所有流量都经过这里转发。

创建 /etc/wireguard/wg0.conf

[Interface]
Address = 192.168.151.1/24
ListenPort = 24356
PrivateKey = <服务器私钥>

# 启用 IP 转发(让 Linux 转发不同网段的流量)
PostUp = sysctl -w net.ipv4.ip_forward=1

# 配置 iptables:允许 WireGuard 接口的转发,并做 NAT
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer] # 家庭网络 A - OpenWrt 路由器
PublicKey = <路由器A的公钥>
AllowedIPs = 192.168.151.2/32, 192.168.2.0/24

[Peer] # 家庭网络 B - OpenWrt 路由器
PublicKey = <路由器B的公钥>
AllowedIPs = 192.168.151.3/32, 192.168.4.0/24

[Peer] # MacBook
PublicKey = <笔记本的公钥>
AllowedIPs = 192.168.151.4/32

[Peer] # iPhone
PublicKey = <iPhone的公钥>
AllowedIPs = 192.168.151.5/32

启动服务并配置防火墙:

# 启用 WireGuard 并设置开机自启
sudo systemctl enable --now wg-quick@wg0

# 开放 UDP 端口
sudo ufw allow 24356/udp

# 验证隧道状态
sudo wg show

wg show 的输出会显示每个 Peer 的最近握手时间和传输流量。如果某个 Peer 的 latest handshake 是空的,说明连接还没建立成功,需要排查。

5. OpenWrt 路由器配置

路由器是这个方案的关键,它作为网关,让整个局域网的设备无感知地访问远端网络。

WireGuard 配置文件(也可以在 LuCI Web 界面中配置):

[Interface]
PrivateKey = <路由器私钥>
Address = 192.168.151.2/24

[Peer]
PublicKey = <服务器公钥>
Endpoint = 203.0.113.1:24356
AllowedIPs = 192.168.151.0/24, 192.168.4.0/24
PersistentKeepalive = 25

几个关键配置点:

在 OpenWrt 的防火墙设置中,还需要:

  1. 将 WireGuard 接口加入一个防火墙区域(比如新建一个 vpn 区域)
  2. 允许 lanvpn 的转发
  3. 允许 vpnlan 的转发(如果需要远端访问本地设备)

6. 移动设备配置

手机和笔记本的配置相对简单:

[Interface]
PrivateKey = <设备私钥>
Address = 192.168.151.4/24
DNS = 192.168.151.1

[Peer]
PublicKey = <服务器公钥>
Endpoint = 203.0.113.1:24356
AllowedIPs = 192.168.151.0/24, 192.168.2.0/24, 192.168.4.0/24
PersistentKeepalive = 25

这里 AllowedIPs 包含了所有需要访问的网段。注意不要设成 0.0.0.0/0(除非你想让所有流量都走 VPN),那样会把所有流量都转发到服务器,增加延迟也浪费带宽。

DNS = 192.168.151.1 是可选的,如果你在 ECS 上跑了 DNS 服务(比如 Pi-hole)可以用这个配置,否则删掉就行。

7. 验证连通性

所有节点配好之后,逐一测试:

# 在 ECS 上查看所有 Peer 状态
sudo wg show

# 从移动设备 ping 各节点
ping 192.168.151.1   # ECS 服务器
ping 192.168.151.2   # 路由器 A 的 VPN IP
ping 192.168.2.1     # 路由器 A 的 LAN IP
ping 192.168.4.1     # 路由器 B 的 LAN IP

# 跨网段测试(从家庭网络 A 的设备访问家庭网络 B)
ping 192.168.4.100   # 家庭网络 B 中的某台设备

# 查看路由表,确认 VPN 路由正确
ip route | grep wg0

注意事项和排错

安全加固

常见问题排查

隧道建不起来:

  1. 确认双方公钥配置正确(最常见的错误就是公钥私钥搞反了)
  2. 确认 ECS 安全组和系统防火墙都放行了 UDP 端口
  3. tcpdump -i eth0 udp port 24356 在服务器上抓包,看看有没有数据到达

能 ping 通 VPN IP 但访问不了对端内网:

  1. 检查 ECS 上的 IP 转发是否开启:cat /proc/sys/net/ipv4/ip_forward,应该是 1
  2. 检查 iptables FORWARD 规则是否生效
  3. 确认 AllowedIPs 包含了对端的内网网段

OpenWrt 局域网设备无法访问远端:

  1. 检查 OpenWrt 防火墙是否允许 lan 到 vpn 区域的转发
  2. 确认路由表中有到远端网段的路由
  3. 在路由器上 traceroute 看看流量是否经过了 WireGuard 接口

持久化和自启动

确保网络重启后 WireGuard 自动恢复:

# ECS 上
sudo systemctl enable wg-quick@wg0

# 确认 IP 转发在重启后仍然生效
echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl -p /etc/sysctl.d/99-wireguard.conf

OpenWrt 通过 LuCI 配置的接口默认会开机自启,不需要额外操作。

使用体验

用了几个月下来,几点感受:

如果设备多了,手动管理配置文件会比较麻烦,可以考虑用 wg-easy 这个项目,它提供了一个简洁的 Web 界面来管理 WireGuard。

相关资源