概念:关于Moon和控制器后台

之前写过一篇使用搭建zerotier私服的文章:
使用Github生成你的Zerotier私服docker镜像
虽然客户端用起来比Moon方便,但自建私服也有缺点,比如不能白嫖官方的节点,数据备份不够方便,节点单一。因此Moon就成为了另一种选择,此外,也可以和私服一样,搭建自己的管理后台,不受官方后台的限制。
Zerotier服务分为两部分,控制器和根。事实上,Zerotier官方提供了自建的文档,其中web后台属于“controllers(控制器)”,控制器是开源的,但不提供webui,GitHub上有开源的ui项目,比如zero-ui和ztncui。控制器使用根的API创建和管理网络,不参与流量通信。而根服务器(Root Server)负责流量转发和P2P通信,根服务器如果是完全自建的话,那就是私服,不参与官方的节点网络,也就是Zerotier中的“Planet(行星节点)”的概念。如果想使用官方的Planet的同时使用自己的根服务器,那就是以Moon(月亮节点)的形式加入到网络中。两者用起来其实没有区别,只是标识不同,无论是自建的Planet还是Moon,都可以被自建的控制器调用。
但有一点需要注意,自建控制器的网络和官方web后台不通用,你不会在官方web后台看到你在自建控制器上创建的网络,反过来也一样,自建控制器也看不到官方控制器创建的网络。但网络ID的加入是可以通用的,即使你不搭建自己的Moon节点,同样也可以使用自己的控制器+官方的Planet进行通信。

搭建控制器

控制器可以选择zeroui或者ztncui,这里使用比较简洁的zeroui做介绍。
首先,在服务器上安装好zerotier并启动,安装过程不详述。

1
2
3
4
5
6
# 安装Zerotier
curl -s https://install.zerotier.com | sudo bash
# 加入开机启动
systemctl enable zerotier-one
# 启动服务
systemctl start zerotier-one

为了数据方便管理和快捷搭建,使用docker运行控制器。安装docker-compose。新建一个你要保存数据的文件夹,比如/home/zero/,新建docker-compose.yaml。
/home/zero/docker-compose.yaml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
version: "3"

services:
  zero-ui:
    image: dec0dos/zero-ui:latest
    container_name: zero-ui
    restart: unless-stopped
    volumes:
      - /var/lib/zerotier-one:/var/lib/zerotier-one
      - ./data:/app/backend/data
    environment:
      - ZU_CONTROLLER_ENDPOINT=http://127.0.0.1:9993/
      - ZU_SECURE_HEADERS=false
      - ZU_DEFAULT_USERNAME=登录的用户名
      - ZU_DEFAULT_PASSWORD=登录的密码
    network_mode: "host"

启动docker:

1
2
cd /home/zero/
docker-compose up -d  

需要对外开放的防火墙端口:

作用端口
zero-ui后台webTCP 4000

你可以对4000端口使用caddy或者nginx进行本地反代,加上https,如果你使用https请设置ZU_SECURE_HEADERS=true(自动跳转https)。
登录后台管理地址:http://IP:4000 , zeroui的界面基本跟官方相似并且更简洁好看,不用多介绍就可以上手。
如果遇到无法访问或者启动的问题,可以查看一下日志:

1
docker-compose logs -f

搭建Moon

搭建Moon官方也有指南,这里简单总结一下。
运行Moon节点模板工具,看一下模板长什么样:
zerotier-idtool initmoon /var/lib/zerotier-one/identity.public
可以看到输出了一个类似一下内容的模板:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    {
      "id": "deadbeef00",
      "objtype": "world",
      "roots": [
        {
          "identity": "deadbeef00:0:34031483094...",
          "stableEndpoints": []
        }
      ],
      "signingKey": "b324d84cec708d1b51d5ac0ce3f54e58d8944b5...",
      "signingKey_SECRET": "ffc5dd0b2baf1c9b220de...",
      "updatesMustBeSignedBy": "b324d84cec708d1b51d5c0b52632...",
      "worldType": "moon"
    }

其中,id就是节点的id,这个在zerotier客户端右键或者运行zerotier-cli info都可以看到,我们要关心的是roots下面的内容。identity其实就是/var/lib/zerotier-one/identity.public这个文件里面的内容,是这个节点的唯一标识,而stableEndpoints就是需要我们补充的东西,里面填服务器的IPV4或者IPV6地址。
导出Moon模板:
zerotier-idtool initmoon /var/lib/zerotier-one/identity.public > /tmp/moon.json
编辑moon.json里面的stableEndpoints:
(/9993是表示zerotier默认通信端口UDP:9993)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    {
      "id": "dkisera650",
      "objtype": "world",
      "roots": [
        {
          "identity": "keadbeef00:0:34031483094...",
          "stableEndpoints": [ "103.1.2.3/9993","2001:d234:d234::9993" ]
        }
      ],
      "signingKey": "b324d84cec708d1b51d5ac0ce3f54e58d8944b5...",
      "signingKey_SECRET": "ffc5dd0b2baf1c9b220de...",
      "updatesMustBeSignedBy": "b324d84cec708d1b51d5c0b52632...",
      "worldType": "moon"
    }

如果你只有IPV4或者只有IPV6,填一个即可,格式如下:

1
2
          "stableEndpoints": [ "103.1.2.3/9993" ]
          "stableEndpoints": [ "2001:d234:d234::9993" ]

而如果你要搭建多个Moon节点,也不需要一个个去编辑的,你只需要编辑其中一个生成的Moon模板,修改roots的内容即可。比如上面的模板是节点A生成的,你可以在节点B、节点C…运行一下zerotier-idtool initmoon /var/lib/zerotier-one/identity.public,得到identity那一段,复制出来,然后一段一段插进去节点A的模板里面去就好了,格式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
    {
      "id": "dkisera650",
      "objtype": "world",
      "roots": [
        {
          "identity": "keadbeef00:0:34031483094...",
          "stableEndpoints": [ "103.1.2.3/9993","2001:d234:d234::9993" ]
        },
                {
          "identity": "osgmebeef00:0:688541064...",
          "stableEndpoints": [ "133.7.2.8/9993"]
        },
                {
          "identity": "pdbnkjayef00:0:65231488041...",
          "stableEndpoints": ["2001:8888:d234::9993" ]
        }
      ],
      "signingKey": "b324d84cec708d1b51d5ac0ce3f54e58d8944b5...",
      "signingKey_SECRET": "ffc5dd0b2baf1c9b220de...",
      "updatesMustBeSignedBy": "b324d84cec708d1b51d5c0b52632...",
      "worldType": "moon"
    }

当你把Moon.json编辑好之后,下一步是对Moon.json签名:

1
zerotier-idtool genmoon /tmp/moon.json

运行后会在当前目录生成0000xxxxxxxxxx.moon的文件,把这个文件放到每一个moon节点下面运行:

1
2
3
4
5
6
# 创建moons.d文件夹
mkdir /var/lib/zerotier-one/moons.d/
# 放入moon文件
cp 0000xxxxxxxxxx.moon /var/lib/zerotier-one/moons.d/
# 重启zerotier服务,应用moon
systemctl restart zerotier-one

moon.json含有你节点的密钥信息,不要忘了删除:rm /tmp/moon.json
需要对外开放的防火墙端口:

作用端口
zerotier根通信UDP 9993

客户端应用Moon

  • 标准Linux客户端:如Ubuntu、centos等有官方包的系统,应用方法其实和搭建Moon节点的最后一步差不多一样,为了方便,其实你可以把自己的moon文件放在web上,写一个脚本就可以一键应用、加入网络节点一气呵成:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 创建moons.d文件夹
mkdir /var/lib/zerotier-one/moons.d/
# 下载moon文件
wget https://example.com/00000000axxxx.moon -O  /var/lib/zerotier-one/moons.d/00000000axxxx.moon
# 重启zerotier服务,应用moon
systemctl restart zerotier-one
# 加入网络节点
zerotier-cli join e0axxxxxx2
# 查看peers,确认moon在跑
zerotier-cli peers
# 查看本机信息
zerotier-cli info
# 查看加入的网络
zerotier-cli listnetworks

把脚本保存成moon.sh扔在web上,你就可以curl -s http://example.com/moon.sh | sh一键执行啦~

  • Windows客户端(管理员运行CMD):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
cmd
@echo off
echo 停止zerotier服务
net stop ZeroTierOneService
echo 创建moons.d文件夹
mkdir C:\ProgramData\ZeroTier\One\moons.d
echo 下载moon文件
curl https://example.com/00000000aaxxxxb.moon -o C:\ProgramData\ZeroTier\One\moons.d\00000000aa562e4b.moon
echo 启动zerotier服务
net start ZeroTierOneService
echo 加入网络节点
"C:\Program Files (x86)\ZeroTier\One\zerotier-cli.bat" join xxxxxxxxx
  • 安卓:https://github.com/kaaass/ZerotierFix
  • IOS:目前没有
  • 其他系统,参考下一节在容器中运行zerotier
  • 如何确认Moon节点正常跑了呢?zerotier-cli peers命令可以观察:
    Windows:"C:\Program Files (x86)\ZeroTier\One\zerotier-cli.bat" peers
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# zerotier-cli peers
200 peers
<ztaddr>   <ver>  <role> <lat> <link>   <lastTX> <lastRX> <path>
00aa562e2b 1.10.3 MOON     264 DIRECT   5058     5058     183.245.71.24/22800
2bca99064f 1.10.1 LEAF     230 DIRECT   10313    10313    110.4.0.3/9993
5f1e2945aa 1.10.3 LEAF       5 DIRECT   499      499      221.11.201.11/9993
67603675ab 1.10.3 MOON      17 DIRECT   268      13268    2001:3b6:32b0:9390:d9ce
62f865ae71 -      PLANET   384 DIRECT   20777    185516   50.7.252.138/9993
778cde7190 -      PLANET   213 DIRECT   20777    185682   103.195.103.66/9993
cafe04eba9 -      PLANET   266 DIRECT   20777    185632   84.17.53.155/9993
cafe9efeb9 -      PLANET   177 DIRECT   763      577      104.194.8.134/9993
62f865ae71 -      PLANET   153 DIRECT   15921    105780   2001:49f0:d0db:2::2/9993   

<Role>一列可以看到有MOON的字样,PLANET是官方服务器,LEAF是客户端,可以看到<path>对应着你的MOON服务器IP,而link一列表示中继还是直连,DIRECT就是直连,RELAY就是中继。

  • 小提示:如果加入网络之后在控制界面看不到新的客户端,或者你在控制界面上删除了客户端,你可以在客户端join之后手动在web上添加,方法是右键客户端复制到ID或者运行zerotier-cli info得到id,然后在web界面的Manually Add Member框里面粘贴点加号即可。

在容器中运行Zerotier客户端

一些非标准的Linux系统,运行Zerotier可能不太方便,比如威联通/群晖的NAS,虽然有对应的安装包,但并不好用,更新不及时bug也多操作不方便,这类系统就比较适合在容器中运行Zerotier客户端,数据备份也方便。以威联通为例,打开ContainerStation,点击左边创建->创建应用程序,使用下面的docker compose配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
version: "3"

services:
  zerotier:
    restart: always
    image: zerotier/zerotier:latest
    container_name: zerotier-one
    devices:
      - /dev/net/tun
    network_mode: host
    volumes:
      - '/share/Container/zerotier:/var/lib/zerotier-one'
    cap_add:
      - NET_ADMIN
      - SYS_ADMIN

其中/share/Container/zerotier是你存数据的文件夹,自己设置。容器启动一次后,可以先停止,然后自己在对应挂载的文件夹创建moons.d和复制moon文件进去,然后重新启动容器。其他操作跟Linux一样了,点击进入容器终端操作就是。
需要注意,需要tun驱动。比如alpine linux可以使用以下命令安装:

1
2
3
apk add iproute2
modprobe tun
echo "tun" >> /etc/modules-load.d/tun.conf

数据备份与迁移

对于控制器来说,其实只需要备份一个zeroui的db.json数据文件就可以,按照教程,就在上面的/home/zero/data目录下,非常简单,这就是容器的方便!
对于根(也就是Moon)来说,把/var/lib/zerotier-one/整个目录拷走就是了,非常简单。
根(Moon)挂了不要紧,还有官方的节点,但你的控制器的db.json没了的话你的网络就失去控制了哦~!好在他只有一个文件,备份同步挺简单。

题外话:6plane

zeroui控制器目前还不支持分配IPV6,但可以通过启用6plane的方式自动分配IPV6。
在根上运行以下命令调用API即可:

1
2
3
curl -X POST --header "X-ZT1-Auth: $(cat /var/lib/zerotier-one/authtoken.secret)"  \  
-d '{"v6AssignMode":{"6plane":true}}'  \  
http://localhost:9993/controller/network/<你的NETWORKS的ID>

附录

Zerotier Self Hosting:https://docs.zerotier.com/self-hosting/introduction/
Zerotier Private Root Servers:https://docs.zerotier.com/zerotier/moons/