WireGuard 系列文章(七):使用 WireGuard 和 Netmaker 创建 Full Mesh 网络

本文最后更新于:2022年1月22日 晚上

系列文章前情提要:

  1. WireGuard 系列文章(一):什么是 VPN
  2. WireGuard 系列文章(二):WireGuard 简介 - 快速、现代、安全的 VPN 隧道
  3. WireGuard 系列文章(三):WireGuard 安装
  4. WireGuard 系列文章(四):WireGuard 快速上手
  5. WireGuard 系列文章(五):Netmaker 简介 - 创建和管理 WireGuard 网络的平台
  6. WireGuard 系列文章(六):Netmaker 安装

终于来到一个重要里程碑了,通过 WireGuard + Netmaker 创建 Full Mesh 网络。实现:

  • 多云服务器内网互联
  • 家庭网络路由器内网互联
  • Full Mesh 网络 Node 通过路由器访问其他家庭设备(如电脑、NAS)
  • 办公设备内网互联
  • 手机内网互联

具体的架构图如下图所示:

我的 WireGuard 网络架构概述

开始配置!

创建 Full Mesh 网络

首先通过 Netmaker Dashboard 创建网络,配置如下:

Netmaker 创建网络

  1. 网络名:按需填写(可自动生成)
  2. IPv4 地址范围:按需填写(可自动生成)
  3. 启用:UDP 打洞(方便需要 NAT 的设备接入 Full Mesh 网络)
  4. 关闭:Is Local Network(如果所有设备不是本地网络互联,就关闭)
  5. 关闭:双栈(推荐关闭,减少复杂度)

创建后可以再点击 Network Details 编辑细节,如下图:

包括:

  • IPv6 地址范围
  • 网络接口名称
  • 监听端口
  • Postup
  • Postdown
  • Keepalive
  • 默认外部 DNS
  • MTU
  • 是否允许没有访问密钥的节点注册(出于安全原因,建议关闭)

查看 Netmaker 所在节点状态

创建网络之后,Netmaker 所在节点会自动作为客户端加入,可以在 Nodes 页面查看其状态和信息,如下:

Netmaker Node 状态

Netmaker Node 详细信息

可以在 DNS 页面查看其 DNS 记录,如下:(我实际配置的网络名为:private)

Netmaker DNS 记录

创建访问密钥

Home / Access Keys 页面,创建指定客户端数量(如 10 个,那么这个 key 用 10 次后就自动失效,其他客户端无法再用这个 key 加入网络),如下图:

Netmaker 创建访问密钥

创建后会弹出加入网络的具体命令,如下:

Netclient 加入网络的命令

具体命令如下:

Linux:

1
curl -sfL https://raw.githubusercontent.com/gravitl/netmaker/master/scripts/netclient-install.sh | VERSION=v0.9.1 KEY=$NETMAKER_TOKEN sh -

Docker:

1
docker run -d --network host  --privileged -e TOKEN=$NETMAKER_TOKEN -v /etc/netclient:/etc/netclient --name netclient gravitl/netclient:v0.9.1

Windows (PowerShell Admin):

1
. { iwr -useb  https://raw.githubusercontent.com/gravitl/netmaker/master/scripts/netclient-install.ps1 } | iex; Netclient-Install -version "v0.9.1" -token "$NETMAKER_TOKEN"

手动安装:

1
./netclient join -t $NETMAKER_TOKEN

通过 Netclient 加入网络

按照上面的架构图,需要加入的节点梳理如下:

  1. Linux: 华为、天翼、腾讯、阿里、百度云服务器,通过 Linux 、Docker 或手动安装方式加入。
  2. Windows:办公电脑(按照架构图,家庭电脑和 NAS 直接通过家里路由器路由过去,无需安装 netclient 及 wireguard),通过 Windows 或手动安装方式加入。
  3. OpenWrt: 家庭路由器,通过手动安装方式加入。
  4. Android:手机,暂无法安装 netclient,通过 外部客户端 方式加入。

Linux 和 Windows 不用多说,直接加入即可。

Linux

Linux 执行命令后,会提示加入成功,同时

一方面将 netclient 移动到 /etc/netclient/ 并从 Netmaker pull 配置文件,具体如下:

1
2
3
4
5
6
7
8
9
# tree .
.
├── config
│   ├── backup.netconfig-private
│   ├── netconfig-private
│   ├── nettoken-private
│   ├── secret-private
│   └── wgkey-private
└── netclient

另一方面将 netclient 配置为 systemd 服务,并启动,每 15s 定时去 Netmaker 那 check in。具体如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# ls -l *netclient*
-rw-r--r-- 1 root root 166 Dec 7 02:04 netclient.service
-rw-r--r-- 1 root root 172 Dec 7 02:04 netclient.timer

# cat netclient.service
[Unit]
Description=Network Check
Wants=netclient.timer

[Service]
Type=simple
ExecStart=/etc/netclient/netclient checkin -n all

[Install]
WantedBy=multi-user.target

# cat netclient.timer
[Unit]
Description=Calls the Netmaker Mesh Client Service
Requires=netclient.service

[Timer]
Unit=netclient.service

OnCalendar=*:*:0/15

[Install]
WantedBy=timers.target

check in 成功的日志如下:

1
2
3
4
# ./netclient checkin -n all
2021/12/12 23:10:10 [netclient] running checkin for all networks
2021/12/12 23:10:11 [netclient] checked in successfully for private
2021/12/12 23:10:12 [netclient] checked in successfully for private

Windows

Windows 操作也类似,目录在:C:\ProgramData\Netclient,系统服务如下:

Netclient Windows 服务

⚠️ 注意

我的电脑无论有没有配置代理,在执行 powershell 脚本下载 winsw.exe 过程中始终无法完整下载,出现这种情况,补救措施如下。

  1. 下载 WinSW-x64.exe:https://github.com/winsw/winsw/releases/download/v2.11.0/WinSW-x64.exe 并重命名为 winsw.exe
  2. 拷贝该文件到:C:\ProgramData\Netclient 目录
  3. 用管理员运行 PowerShell,运行:C:\ProgramData\Netclient\winsw.exe install 安装为 windows 服务
  4. 接着运行:C:\ProgramData\Netclient\winsw.exe start 来启动。
  5. 在 Windows 服务中验证是否已安装好并启动:

OpenWrt

对于路由器 openwrt,可以自行编译可以运行的 netclient,然后手动运行即可加入成功。

加入成功后,为了定期运行,可以在 crontab 中添加如下以定期 checkin:

1
2
* * * * * /etc/netclient/netclient checkin --network all &> /dev/null
* * * * * sleep 15; /etc/netclient/netclient checkin --network all &> /dev/null

这两个计划任务变相实现了 每隔 15 秒执行一次 check in 的目的。

小结

至此,除了家庭网络的家庭电脑和 NAS 设备,以及手机之外,其他已经加入了 Full Mesh 网络,可以相互 ping 通。wg show 也能看到 peers 的信息。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# ping 10.88.60.1
PING 10.88.60.1 (10.88.60.1) 56(84) bytes of data.
64 bytes from 10.88.60.1: icmp_seq=1 ttl=64 time=46.1 ms
64 bytes from 10.88.60.1: icmp_seq=2 ttl=64 time=46.0 ms
64 bytes from 10.88.60.1: icmp_seq=3 ttl=64 time=46.1 ms
64 bytes from 10.88.60.1: icmp_seq=4 ttl=64 time=46.0 ms
^C
--- 10.88.60.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 45.963/46.034/46.073/0.044 ms

# wg show
interface: nm-private
public key: <hidden>
private key: (hidden)
listening port: 51821
fwmark: 0x221b

peer: kXmPHKYv6L5c<hidden>nIex7Yd5JFyq6NZB6dFE=
endpoint: <hidden>:51821
allowed ips: 10.88.60.8/32
latest handshake: 25 seconds ago
transfer: 1.74 MiB received, 618.27 KiB sent
persistent keepalive: every 20 seconds

peer: OK7B2QzY8r<hidden>SfIr/tqinSGBd55gjsmgjo=
endpoint: <hidden>:51821
allowed ips: 10.88.60.3/32
latest handshake: 29 seconds ago
transfer: 1.25 MiB received, 316.43 KiB sent
persistent keepalive: every 20 seconds

peer: +SMVJLu<hidden>KkUVSk2aKPdTJ9rd+lK1C4=
endpoint: <hidden>:51822
allowed ips: 10.88.60.6/32
latest handshake: 52 seconds ago
transfer: 316.42 KiB received, 1.25 MiB sent
persistent keepalive: every 20 seconds

peer: U73tngxoP<hidden>YzAhIS8hTfO3Chno3U04=
endpoint: <hidden>:51821
allowed ips: 10.88.60.7/32
latest handshake: 56 seconds ago
transfer: 316.65 KiB received, 1.25 MiB sent
persistent keepalive: every 20 seconds

peer: 5lnsgrK3b<hidden>9x7bdM2nsqqC2CYUY=
endpoint: <hidden>:51821
allowed ips: 10.88.60.1/32
latest handshake: 1 minute, 9 seconds ago
transfer: 443.09 KiB received, 1.16 MiB sent
persistent keepalive: every 20 seconds

peer: 6d9cRCdKcb<hidden>QvfM6AwqoNRADC4VM=
endpoint: <hidden>:51821
allowed ips: 10.88.60.4/32
latest handshake: 1 minute, 36 seconds ago
transfer: 1.25 MiB received, 316.25 KiB sent
persistent keepalive: every 20 seconds

peer: SiNrI37GI<hidden>+G9h0H6IuZJ2iTtGWo=
endpoint: <hidden>:61401
allowed ips: 10.88.60.9/32
latest handshake: 3 days, 1 hour, 47 minutes, 21 seconds ago
transfer: 3.22 MiB received, 9.55 MiB sent
persistent keepalive: every 20 seconds

通过外部客户端加入网络

对于手机,目前是要通过外部客户端的方式加入网络。具体步骤如下:

  1. 选定一台 ** 有公网静态 IP ** 的 Node 作为 Ingress Gateway(可以理解为 WireGuard 的中继服务器),用于接收来自手机的流量并转发,配置也很简单,在 Nodes 页面,点击如下即可将某一 Node 配置:
    将某一 Node 配置为 Ingress Gateway
  2. 手机(安卓设备)下载并安装 WireGuard 原生客户端;
  3. 创建一个 External Client,它会生成一个 WireGuard 配置文件,WireGuard 客户端可以下载该配置文件或者扫描二维码进行连接。如下图:
    Netmaker Ext. Client

Node 通过路由器访问家庭内部局域网

这里家庭内网的电脑和 NAS 并没有直接加入 Full Mesh 网络(直接加入也可以,步骤同上文),而是通过路由器访问 Full Mesh 网络。

到目前为止我们只是打造了一个点对点的 Mesh 网络,各个节点之间都可以通过 WireGuard 的私有网络 IP 进行直连。但我们可以更大胆一点,让每个节点都能访问家庭网络的局域网 IP。以 OpenWrt 为例,假设 OpenWrt 跑在家中,家中的局域网 IP 为 192.168.2.0/24,如何让其他所有节点都能访问这个局域网呢?

其实也很简单,可以将某个节点设置为 Egress Gateway(出口网关),允许将 内部 网络的流量转发到 外部 指定的 IP 范围。这里的 内部 指的是 WireGuard 私有网络,本文中就是 10.88.60.0/24外部 网络指的是家庭局域网网段。

操作步骤如下图:

Netmaker 创建 Egress Gateway

填写局域网的网段(如:192.168.2.0/24 )和出口网卡(如:eth0)。如下图:

Netmaker 创建 Egress Gateway - 2

配置完成后,就会在 OpenWrt 节点配置的 Postup 和 Postdown 中添加相关的 iptables 规则。如下图:

Egress Gateway 自动配置路由规则

wg show 查看如下:

1
2
3
4
5
6
peer: kXmPHKYv6L5cX<hidden>d5JFyq6NZB6dFE=
endpoint: <hidden>:51821
allowed ips: 10.88.60.8/32, 192.168.2.0/24
latest handshake: 25 seconds ago
transfer: 1.74 MiB received, 618.27 KiB sent
persistent keepalive: every 20 seconds

具体的规则为:

1
2
3
4
5
# Postup
iptables -A FORWARD -i nm-private -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# Postdown
iptables -D FORWARD -i nm-private -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

除此之外还会在其他所有节点中添加相关路由表:

1
2
$ ip route|grep "192.168.2.0/24"
192.168.2.0/24 dev nm-private scope link

最终所有的节点都可以访问 OpenWrt 的局域网 IP 了。

总结

至此,我们终于完成了 WireGuard 的系列的一个重要里程碑:通过 WireGuard + Netmaker 配置 Full Mesh 网络,并打通家庭局域网。🎉🎉🎉