前言

最近公司搬了新地址,开发和测试的服务器原来就在办公室放着,现在需要搬到机房,但是新的办公室和机房不在一起,网络不通。

在网上找了一圈,发现了个叫 ZeroTier 的工具,组建局域网比较方便。

官网宣传说:在任何地方安全地连接任何设备:

Securely connect any device, anywhere.

ZeroTier 能够将处于不同网络的设备加入到同一个 VLAN(虚拟局域网),可以通过虚拟 IP 访问设备,也可以设置 DNS 通过域名访问。

看了很多文章都是直接搭建,照着一通操作云里雾里,所以到官网研究了一下,在这里做个记录。

1. 概念

Node

节点,服务端和客户端都称为节点,它们使用相同的软件。可以修改配置文件使节点发挥不同的作用,根据作用可以分为 Planet、Moon 和 Leaf。

Root Server

根服务器,就像 DNS 一样,根服务器是建立网络连接的基础。

Planet

官方的根服务器称为 Planet 。在 ZeroTier 中,有且只有一个 Planet 称为 Earth,目前有 12 台官方服务器,组成两个集群,每个集群有 6 个节点。

Moon

用户自定义的根服务器称为 Moon。Moon 无法控制网络,只能中转网络中的数据。

Leaf

客户端节点。Planet、Moon、Leaf 的程序是一样的,通过不同的配置文件使得程序承担不同的功能。

Network

一个 Network 就是一个虚拟局域网,每个 Network 都有一个 Network ID,设备通过 Network ID 连接到虚拟局域网中。

2. 使用

2.1 注册账号

前往 官方网站 进行注册

2.2 创建网络

1692175466837.png

点一下创建就完成了,不需要其他的设置,注意这个 NETWORK ID 等下要用。

2.3 安装并加入网络

Docker

注意:将下方 abcdefdeadbeef00 替换为自己的 NETWORK ID

直接运行

docker run --name myzerotier --rm --cap-add NET_ADMIN --device /dev/net/tun zerotier/zerotier:latest abcdefdeadbeef00

docker-compose

version: '3.3'
services:
  zerotier:
    devices:
      - /dev/net/tun
    privileged: true
    image: zerotier/zerotier
    network_mode: host
    cap_add:
      - NET_ADMIN
    command: ['abcdefdeadbeef00']
    volumes:
      - ./data:/var/lib/zerotier-oneroot

Linux

使用以下命令进行安装

curl -s https://install.zerotier.com | sudo bash

如果安装了 GPG,需要多加一些参数

curl -s 'https://raw.githubusercontent.com/zerotier/ZeroTierOne/master/doc/contact%40zerotier.com.gpg' | gpg --import && \
if z=$(curl -s 'https://install.zerotier.com/' | gpg); then echo "$z" | sudo bash; fi
  • 加入一个网络:zerotier-cli join ################
  • 离开一个网络:zerotier-cli join ################
  • 列出当前加入的网络:zerotier-cli listnetworks

Windows

Windows 客户端 下载后安装

安装完成后,点击右下角图标,点击 Join New Network...

其他安装方式参考 官网

2.4 查看网络状态

使用 zerotier-cli peers 查看节点信息,可以看到 link 一栏,DIRECT 代表 P2P 直连,RELAY 代表通过服务器中转。

直接使用 ZeroTier 的官方服务器延迟比较高,通过 PING 可以查看延迟,可以看到还有丢包的情况 1693805969682.png

为了降低延迟,有条件的话我们可以搭建自己的服务器,ZeroTier 把私有的服务器称为 MOON

3. MOON

3.1 搭建 MOON

当一个节点使用了 Moon 时,节点会将 Moon 服务器添加到它的根服务器集合中,此时节点同时使用了 Planet 和 Moon 的服务器。当无法连接到 Planet,或者 Moon 的速度比 Planet 快时,节点会使用 Moon。

每个自定义服务器都有一个定义文件称为 identity.public 文件

以 Linux 为例,准备一个 Linux 服务器,安装好 ZeroTier。

连接服务器,随便在哪个路径里执行命令,创建一个定义文件

zerotier-idtool initmoon identity.public >> moon.json

文件内容类似:

    {
      "id": "deadbeef00",
      "objtype": "world",
      "roots": [
        {
          "identity": "deadbeef00:0:34031483094...",
          "stableEndpoints": []
        }
      ],
      "signingKey": "b324d84cec708d1b51d5ac03e75afba501a12e2124705ec34a614bf8f9b2c800f44d9824ad3ab2e3da1ac52ecb39ac052ce3f54e58d8944b52632eb6d671d0e0",
      "signingKey_SECRET": "ffc5dd0b2baf1c9b220d1c9cb39633f9e2151cf350a6d0e67c913f8952bafaf3671d2226388e1406e7670dc645851bf7d3643da701fd4599fedb9914c3918db3",
      "updatesMustBeSignedBy": "b324d84cec708d1b51d5ac03e75afba501a12e2124705ec34a614bf8f9b2c800f44d9824ad3ab2e3da1ac52ecb39ac052ce3f54e58d8944b52632eb6d671d0e0",
      "worldType": "moon"
    }

在其中 roots/stableEndpoints 中填写 公网IP/PORT,如果有 IPv6 地址也可以填上:

    {
      "id": "deadbeef00",
      "objtype": "world",
      "roots": [
        {
          "identity": "deadbeef00:0:34031483094...",
          "stableEndpoints": [ "10.0.0.2/9993","2001:abcd:abcd::1/9993" ]
        }
      ],
      "signingKey": "b324d84cec708d1b51d5ac03e75afba501a12e2124705ec34a614bf8f9b2c800f44d9824ad3ab2e3da1ac52ecb39ac052ce3f54e58d8944b52632eb6d671d0e0",
      "signingKey_SECRET": "ffc5dd0b2baf1c9b220d1c9cb39633f9e2151cf350a6d0e67c913f8952bafaf3671d2226388e1406e7670dc645851bf7d3643da701fd4599fedb9914c3918db3",
      "updatesMustBeSignedBy": "b324d84cec708d1b51d5ac03e75afba501a12e2124705ec34a614bf8f9b2c800f44d9824ad3ab2e3da1ac52ecb39ac052ce3f54e58d8944b52632eb6d671d0e0",
      "worldType": "moon"
    }

如果你有多个服务器可以一起添加进来,比如:

    {
      "id": "deadbeef00",
      "objtype": "world",
      "roots": [
        {
          "identity": "deadbeef00:0:34031483094...",
          "stableEndpoints": [ "10.0.0.2/9993","2001:abcd:abcd::1/9993" ]
        },
        {
          "identity": "feedbeef11:0:83588158384...",
          "stableEndpoints": [ "10.0.0.3/9993","2001:abcd:abcd::3/9993" ]
        }
      ],
      "signingKey": "b324d84cec708d1b51d5ac03e75afba501a12e2124705ec34a614bf8f9b2c800f44d9824ad3ab2e3da1ac52ecb39ac052ce3f54e58d8944b52632eb6d671d0e0",
      "signingKey_SECRET": "ffc5dd0b2baf1c9b220d1c9cb39633f9e2151cf350a6d0e67c913f8952bafaf3671d2226388e1406e7670dc645851bf7d3643da701fd4599fedb9914c3918db3",
      "updatesMustBeSignedBy": "b324d84cec708d1b51d5ac03e75afba501a12e2124705ec34a614bf8f9b2c800f44d9824ad3ab2e3da1ac52ecb39ac052ce3f54e58d8944b52632eb6d671d0e0",
      "worldType": "moon"
    }

执行命令,生成签名文件,文件名称像是 000000deadbeef00.moon

zerotier-idtool genmoon moon.json

到 ZeroTier 的配置文件 /var/lib/zerotier-one,在配置文件中创建一个文件夹 moons.d,把上一步生成的文件 000000deadbeef00.moon 复制到 moons.d

防火墙开启 9993 端口的 TCP/UDP 协议,如果中转效果不理想,可以把所有端口都开启

重启 MOON 服务器

3.2 连接 MOON

客户端可以通过两种方式连接 MOON:

  1. 将签名文件 000000deadbeef00.moon 复制到客户端配置文件的 moons.d 文件夹中,然后重启
  2. 使用命令 zerotier-cli orbit deadbeef00 deadbeef00 添加 MOON,第一个参数是 moon.json 中的 id,第二个参数是 moon.json roots 中任意一个节点的 identity中的第一部分

4. 访问内网其他设备

前面的步骤完成之后,可以访问到内网运行了 ZeroTier 的机器,但是不能访问内网的其他机器。

众所周知,路由器、交换机本质上就是一台电脑,只要连上路由器或者交换机就能访问同网段的其他设备。

那么我们只要将运行了 ZeroTier 的机器当作一个交换机,就可以通过它访问内网的其他设备了。

Ubuntu

创建配置文件 /opt/zerotier-nat,将以下内容复制到文件中 其中 ens18 更换为内网 ZeroTier 机器的网口名称,10.147.18.0/24 更换为你的虚拟网段

iptables -A FORWARD -o ens18 -i ztbto3rof2 -s 10.147.18.0/24 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -F POSTROUTING
iptables -t nat -A POSTROUTING -o ens18 -j MASQUERADE

修改文件权限 chmod 755 /opt/zerotier-nat

进入目录 /usr/lib/systemd/system

创建文件zerotier-nat.service ,将以下内容复制到文件中

[Unit]
Description=zerotier-nat
After=networking.service

[Service]
Type=oneshot
ExecStart=/bin/bash -e /opt/zerotier-nat
KillSignal=SIGINT

[Install]
WantedBy=multi-user.target