diff --git a/Dockerfile b/Dockerfile index ef315cc..a76d3fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,42 +1,12 @@ -FROM alpine:latest - -ADD ./server.sh /app/ -ADD ./patch /opt/patch/ - -VOLUME ["/var/lib/zerotier-one/"] - - - -RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories &&\ - apk update &&\ - apk add git python3 nodejs npm make g++ linux-headers zerotier-one &&\ - npm config set registry http://registry.npm.taobao.org &&\ - - # 安装ztncui - cd /opt && git clone https://github.91chi.fun/https://github.com/key-networks/ztncui.git &&\ - cd ztncui/src && npm install -g node-gyp && npm install &&\ - cp -pv ./etc/default.passwd ./etc/passwd &&\ - echo 'HTTP_PORT=3443' > .env&&\ - echo 'NODE_ENV=production' >> .env &&\ - echo 'HTTP_ALL_INTERFACES=true' >> .env &&\ - - # 添加补丁 - cd /opt && \ - git clone https://github.91chi.fun/https://github.com/zerotier/ZeroTierOne.git && \ - - cd /var/lib/zerotier-one && \ - zerotier-idtool generate identity.public identity.secret &&\ - zerotier-idtool initmoon identity.public >> moon.json &&\ - - cp /opt/patch/* . &&\ - python3 patch.py &&\ - zerotier-idtool genmoon moon.json &&\ - mkdir moons.d && cp ./*.moon ./moons.d &&\ - - rm /opt/ZeroTierOne/attic/world/mkworld.cpp &&\ - cp mkworld.cpp /opt/ZeroTierOne/attic/world/ &&\ - cd /opt/ZeroTierOne/attic/world/ && \ - sh build.sh - -WORKDIR /app/ -CMD ["sh","./server.sh"] +FROM alpine:latest + +ADD ./init.sh /app/ +ADD ./gen_world.sh /app/ +ADD ./patch /opt/patch/ + +VOLUME ["/var/lib/zerotier-one/"] + +RUN cd /app && sh init.sh + +WORKDIR /app/ +CMD /bin/sh -c "zerotier-one -d; cd /opt/ztncui/src;npm start" diff --git a/README.md b/README.md index 1158f94..76978f8 100644 --- a/README.md +++ b/README.md @@ -1,97 +1,93 @@ -# Docker-zerotier-planet -私有部署zeroteir-planet服务 - -zerotier是一个非常好用的私有组网的软件,但是官方提供的服务器离我们比较远,自建planet服务器可以帮我们解决很多与网络有关的问题 - - -# 准备条件 -- 具有公网ip的服务器(需要开放3443/tcp端口,9992/tcp端口,9992/udp端口) -- 安装docker - -# 开始 -## 1.下载项目源码 -``` -git clone https://github.com.cnpmjs.org/xubiaolin/docker-zerotier-planet.git -``` -## 2.修改项目中的patch/patch.json - -将其中的ip地址修改为你服务器的ip地址,端口保留不变即可 - - -## 3.在包含Dockerfile的目录下打包镜像 -如果您不是第一次使用该项目,您需要先执行以下命令 -``` -rm -rf /opt/zerotier-planet -docker stop zerotier-planet -docker rm zerotier-planet -docker rmi zerotier-planet -``` -打包镜像 -``` -docker build -t zerotier-planet:latest . -``` -打包预计需要2-5分钟,具体需要看网络与机型 - - -# 启动项目 - -启动服务 -``` -docker run -d --name zerotier-planet -p 3443:3443 -p 9992:9993 -p 9992:9993/udp -v /opt/zerotier-planet:/var/lib/zerotier-one --restart unless-stopped zerotier-planet:latest -``` - - -# 创建网络 -服务器需要开放3443端口 -然后访问http://ip:3443 即可进入管理后台 - -![ui](webui.png) - - -使用默认账号为:admin - -默认密码为:password - -进入后创建一个网络,可以得到一个网络ID -通过官方的app就可以直接连接这个网络ID了,下面的步骤为可选操作。 - -# 【可选】客户端配置 -首先将服务器/opt/zerotier-planet 目录下的planet文件下载到本地以备用 - -## linux 客户端配置 -安装zerotier-one客户端 -``` -curl -s https://install.zerotier.com | sudo bash -``` -进入/var/lib/zerotier-one目录下, -删除目录下的planet文件,然后把从服务器下载的planet文件替换过来 - -重启一下zerotier-one服务 -debian系使用命令 -``` -service zerotier-one restart -``` - -然后执行zerotier-cli join 网络ID - -成功后可以在管理后台上面看到一个新增的members,此时我们需要授权,否则将无法访问。 - -![auth](auth.png) - -其他客户端加入也是一样要进行授权操作操作 - -## windows 客户端配置 -windows -将planet文件覆盖粘贴到C:\ProgramData\ZeroTier\One中 - -windows搜索服务,并重启zeroiter-one - -powershell(admin)中执行zerotier-cli listpeers查看planet是否生效 - -## 安卓客户端配置 -[Zerotier 非官方安卓客户端发布:支持自建 Moon 节点 - V2EX](https://www.v2ex.com/t/768628) - -# 参考链接 -[zerotier-虚拟局域网详解](https://www.glimmer.ltd/2021/3299983056/) - -[五分钟自建 ZeroTier 的 Planet/Controller](https://v2ex.com/t/799623) +# Docker-zerotier-planet +私有部署 `zeroteir-planet` 服务 + +zerotier 是一个非常好用的私有组网的软件,但是官方提供的服务器离我们比较远,自建planet服务器可以帮我们解决很多与网络有关的问题 + + +# 一:准备条件 +- 具有公网ip的服务器(需要开放3443/tcp端口,9993/tcp端口,9993/udp端口) +- 安装docker + +# 二:开始 +## 1.下载项目源码 +``` +git clone http://github.markxu.vip/https://github.com/xubiaolin/docker-zerotier-planet.git +``` +## 2.修改配置 + +修改项目中的patch/patch.json,将其中的ip地址修改为你服务器的ip地址,端口保留不变即可 + +## 3.一键部署 +启动时会关闭9993端口的服务,请注意 +``` +cd docker-zerotier-planet +./deploy.sh +``` +打包预计需要3-5分钟,具体需要看网络与机型 + + +**防火墙需要开放 `3443/tcp, 9993/tcp, 9993/udp` 这三个端口** + +**planet 文件在`/opt/planet`, 客户端直连时需要替换客户端的planet** + +# 三:创建网络 +访问 http://ip:3443 即可进入controller页面 + +![ui](webui.png) + + +使用默认账号为:`admin` + +默认密码为:`password` + +进入后创建一个网络,可以得到一个网络ID +# 四:客户端配置 +首先将服务器 `/opt/zerotier-planet` 目录下的 planet 文件下载到本地以备用 + +## 4.1linux 客户端配置 +安装zerotier-one客户端 +``` +curl -s https://install.zerotier.com | sudo bash +``` +进入`/var/lib/zerotier-one`目录下, +删除目录下的planet文件,然后把从服务器下载的planet文件替换过来 + +重启一下zerotier-one服务 +debian系使用命令 +``` +service zerotier-one restart +``` + +执行 `zerotier-cli listpeers` 可以查看 peers + +![linux_ok](linux_planet_ok.png) + +如果和上图一样出现了PLANET字样,则表示成功了 + +---------------------------------------- + +执行`zerotier-cli join 网络ID`,可以加入到网络中, + +成功后可以在管理后台上面看到一个新增的 members ,此时我们需要授权,否则将无法访问。 + +![auth](auth.png) + +其他客户端加入也是一样要进行授权操作操作 + +## 4.2 windows 客户端配置 +windows +将 planet 文件覆盖粘贴到`C:\ProgramData\ZeroTier\One`中 + +windows 搜索服务,并重启 zeroiter-one + +powershell(admin)中执行`zerotier-cli listpeers`查看 planet 是否生效 +![win_ok](win_planet_ok.png) + + +## 4.3 安卓客户端配置 +[Zerotier 非官方安卓客户端发布:支持自建 Moon 节点 - V2EX](https://www.v2ex.com/t/768628) + +# 参考链接 +[zerotier-虚拟局域网详解](https://www.glimmer.ltd/2021/3299983056/) + +[五分钟自建 ZeroTier 的 Planet/Controller](https://v2ex.com/t/799623) diff --git a/deploy.sh b/deploy.sh old mode 100644 new mode 100755 index 409af6b..5f0b873 --- a/deploy.sh +++ b/deploy.sh @@ -1,15 +1,26 @@ #!/bin/sh imageName="zerotier-planet" +docker network create zerotier + echo "清除原有内容" -rm -rf /opt/$imageName +rm /opt/planet docker stop $imageName docker rm $imageName docker rmi $imageName + echo "打包镜像" -docker build -t $imageName:latest . +docker build --network zerotier -t $imageName . echo "启动服务" for i in $(lsof -i:9993 -t);do kill -2 $i;done -docker run -d --network host --name $imageName -p 3443:3443 -p 9993:9993 -p 9993:9993/udp -v /opt/$imageName:/var/lib/zerotier-one --restart unless-stopped $imageName:latest +docker run -d --network zerotier --name $imageName -p 3443:3443 -p 9993:9993 -p 9993:9993/udp --dns 223.5.5.5 --dns 223.6.6.6 --restart unless-stopped $imageName + +sleep 10s +echo "生成世界" +docker exec -it $imageName sh /app/gen_world.sh +docker cp $imageName:/opt/ZeroTierOne/attic/world/world.bin /opt/planet + +echo "------------------" +echo "现在已经配置好了,planet文件在/opt/planet, 客户端连接时需要替换该planet" \ No newline at end of file diff --git a/gen_world.sh b/gen_world.sh new file mode 100644 index 0000000..d86e9ce --- /dev/null +++ b/gen_world.sh @@ -0,0 +1,10 @@ +cd /var/lib/zerotier-one && zerotier-idtool initmoon identity.public > moon.json + +# 添加补丁 +cd /opt/patch && python3 patch.py +cd /var/lib/zerotier-one && zerotier-idtool genmoon moon.json && mkdir moons.d && cp ./*.moon ./moons.d + +# 生成世界 +cd /opt/ZeroTierOne/attic/world/ +sh build.sh +./mkworld \ No newline at end of file diff --git a/init.sh b/init.sh new file mode 100644 index 0000000..5571851 --- /dev/null +++ b/init.sh @@ -0,0 +1,21 @@ +sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories +apk update +apk add git python3 nodejs npm make g++ linux-headers zerotier-one +npm config set registry http://registry.npm.taobao.org && npm install -g node-gyp + +echo "下载源码中,源码文件较大,请耐心等待;如果源码下载失败,请重新执行该脚本" +# 下载源码 +cd /opt && git clone http://github.markxu.vip/https://github.com/key-networks/ztncui.git +if [ "$?"-ne 0]; then echo "下载源码出错,请重试"; exit 1; fi + +cd /opt && git clone http://github.markxu.vip/https://github.com/zerotier/ZeroTierOne.git +if [ "$?"-ne 0]; then echo "下载源码出错,请重试"; exit 1; fi + +# 配置ztncui +cd /opt/ztncui/src && npm install +cp -pv ./etc/default.passwd ./etc/passwd +echo 'HTTP_PORT=3443' >.env +echo 'NODE_ENV=production' >>.env +echo 'HTTP_ALL_INTERFACES=true' >>.env + + diff --git a/linux_planet_ok.png b/linux_planet_ok.png new file mode 100644 index 0000000..92ac5cd Binary files /dev/null and b/linux_planet_ok.png differ diff --git a/patch/mkworld.cpp b/patch/mkworld.cpp index 49181a7..7f6a051 100644 --- a/patch/mkworld.cpp +++ b/patch/mkworld.cpp @@ -1,119 +1,119 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This utility makes the World from the configuration specified below. - * It probably won't be much use to anyone outside ZeroTier, Inc. except - * for testing and experimentation purposes. - * - * If you want to make your own World you must edit this file. - * - * When run, it expects two files in the current directory: - * - * previous.c25519 - key pair to sign this world (key from previous world) - * current.c25519 - key pair whose public key should be embedded in this world - * - * If these files do not exist, they are both created with the same key pair - * and a self-signed initial World is born. - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -using namespace ZeroTier; - -int main(int argc,char **argv) -{ - std::string previous,current; - if ((!OSUtils::readFile("previous.c25519",previous))||(!OSUtils::readFile("current.c25519",current))) { - C25519::Pair np(C25519::generate()); - previous = std::string(); - previous.append((const char *)np.pub.data,ZT_C25519_PUBLIC_KEY_LEN); - previous.append((const char *)np.priv.data,ZT_C25519_PRIVATE_KEY_LEN); - current = previous; - OSUtils::writeFile("previous.c25519",previous); - OSUtils::writeFile("current.c25519",current); - fprintf(stderr,"INFO: created initial world keys: previous.c25519 and current.c25519 (both initially the same)" ZT_EOL_S); - } - - if ((previous.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))||(current.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))) { - fprintf(stderr,"FATAL: previous.c25519 or current.c25519 empty or invalid" ZT_EOL_S); - return 1; - } - C25519::Pair previousKP; - memcpy(previousKP.pub.data,previous.data(),ZT_C25519_PUBLIC_KEY_LEN); - memcpy(previousKP.priv.data,previous.data() + ZT_C25519_PUBLIC_KEY_LEN,ZT_C25519_PRIVATE_KEY_LEN); - C25519::Pair currentKP; - memcpy(currentKP.pub.data,current.data(),ZT_C25519_PUBLIC_KEY_LEN); - memcpy(currentKP.priv.data,current.data() + ZT_C25519_PUBLIC_KEY_LEN,ZT_C25519_PRIVATE_KEY_LEN); - - // ========================================================================= - // EDIT BELOW HERE - - std::vector roots; - - const uint64_t id = ZT_WORLD_ID_EARTH; - const uint64_t ts = 1567191349589ULL; // August 30th, 2019 - - //__PATCH_REPLACE__ - - // END WORLD DEFINITION - // ========================================================================= - - fprintf(stderr,"INFO: generating and signing id==%llu ts==%llu" ZT_EOL_S,(unsigned long long)id,(unsigned long long)ts); - - World nw = World::make(World::TYPE_PLANET,id,ts,currentKP.pub,roots,previousKP); - - Buffer outtmp; - nw.serialize(outtmp,false); - World testw; - testw.deserialize(outtmp,0); - if (testw != nw) { - fprintf(stderr,"FATAL: serialization test failed!" ZT_EOL_S); - return 1; - } - - OSUtils::writeFile("world.bin",std::string((const char *)outtmp.data(),outtmp.size())); - fprintf(stderr,"INFO: world.bin written with %u bytes of binary world data." ZT_EOL_S,outtmp.size()); - - fprintf(stdout,ZT_EOL_S); - fprintf(stdout,"#define ZT_DEFAULT_WORLD_LENGTH %u" ZT_EOL_S,outtmp.size()); - fprintf(stdout,"static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {"); - for(unsigned int i=0;i 0) - fprintf(stdout,","); - fprintf(stdout,"0x%.2x",(unsigned int)d[i]); - } - fprintf(stdout,"};" ZT_EOL_S); - - return 0; +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * This utility makes the World from the configuration specified below. + * It probably won't be much use to anyone outside ZeroTier, Inc. except + * for testing and experimentation purposes. + * + * If you want to make your own World you must edit this file. + * + * When run, it expects two files in the current directory: + * + * previous.c25519 - key pair to sign this world (key from previous world) + * current.c25519 - key pair whose public key should be embedded in this world + * + * If these files do not exist, they are both created with the same key pair + * and a self-signed initial World is born. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace ZeroTier; + +int main(int argc,char **argv) +{ + std::string previous,current; + if ((!OSUtils::readFile("previous.c25519",previous))||(!OSUtils::readFile("current.c25519",current))) { + C25519::Pair np(C25519::generate()); + previous = std::string(); + previous.append((const char *)np.pub.data,ZT_C25519_PUBLIC_KEY_LEN); + previous.append((const char *)np.priv.data,ZT_C25519_PRIVATE_KEY_LEN); + current = previous; + OSUtils::writeFile("previous.c25519",previous); + OSUtils::writeFile("current.c25519",current); + fprintf(stderr,"INFO: created initial world keys: previous.c25519 and current.c25519 (both initially the same)" ZT_EOL_S); + } + + if ((previous.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))||(current.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))) { + fprintf(stderr,"FATAL: previous.c25519 or current.c25519 empty or invalid" ZT_EOL_S); + return 1; + } + C25519::Pair previousKP; + memcpy(previousKP.pub.data,previous.data(),ZT_C25519_PUBLIC_KEY_LEN); + memcpy(previousKP.priv.data,previous.data() + ZT_C25519_PUBLIC_KEY_LEN,ZT_C25519_PRIVATE_KEY_LEN); + C25519::Pair currentKP; + memcpy(currentKP.pub.data,current.data(),ZT_C25519_PUBLIC_KEY_LEN); + memcpy(currentKP.priv.data,current.data() + ZT_C25519_PUBLIC_KEY_LEN,ZT_C25519_PRIVATE_KEY_LEN); + + // ========================================================================= + // EDIT BELOW HERE + + std::vector roots; + + const uint64_t id = ZT_WORLD_ID_EARTH; + const uint64_t ts = 1567191349589ULL; // August 30th, 2019 + + //__PATCH_REPLACE__ + + // END WORLD DEFINITION + // ========================================================================= + + fprintf(stderr,"INFO: generating and signing id==%llu ts==%llu" ZT_EOL_S,(unsigned long long)id,(unsigned long long)ts); + + World nw = World::make(World::TYPE_PLANET,id,ts,currentKP.pub,roots,previousKP); + + Buffer outtmp; + nw.serialize(outtmp,false); + World testw; + testw.deserialize(outtmp,0); + if (testw != nw) { + fprintf(stderr,"FATAL: serialization test failed!" ZT_EOL_S); + return 1; + } + + OSUtils::writeFile("world.bin",std::string((const char *)outtmp.data(),outtmp.size())); + fprintf(stderr,"INFO: world.bin written with %u bytes of binary world data." ZT_EOL_S,outtmp.size()); + + fprintf(stdout,ZT_EOL_S); + fprintf(stdout,"#define ZT_DEFAULT_WORLD_LENGTH %u" ZT_EOL_S,outtmp.size()); + fprintf(stdout,"static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {"); + for(unsigned int i=0;i 0) + fprintf(stdout,","); + fprintf(stdout,"0x%.2x",(unsigned int)d[i]); + } + fprintf(stdout,"};" ZT_EOL_S); + + return 0; } \ No newline at end of file diff --git a/patch/patch.json b/patch/patch.json index a5476b0..73081d7 100644 --- a/patch/patch.json +++ b/patch/patch.json @@ -1,5 +1,5 @@ -{ - "stableEndpoints": [ - "82.157.68.236/9993" - ] -} +{ + "stableEndpoints": [ + "82.157.68.236/9993" + ] +} diff --git a/patch/patch.py b/patch/patch.py index f171fb4..8eeafdb 100644 --- a/patch/patch.py +++ b/patch/patch.py @@ -1,51 +1,51 @@ -import os -import json - - -def patch_moon(): - patch_data = dict() - with open("patch.json", "r") as f: - patch_data = json.load(f) - - moon = dict() - with open("moon.json", "r") as f: - moon = json.load(f) - - endpoint_patch = patch_data.get("stableEndpoints", []) - if len(endpoint_patch) == 0: - print("请配置endpoint!") - exit(1) - - moon["roots"][0]["stableEndpoints"] = endpoint_patch - - with open("moon.json", "w+") as f: - f.write(json.dumps(moon)) - - -def patch_world(): - moon = dict() - - file_moon = open("moon.json", "r") - moon = json.load(file_moon) - file_moon.close() - - middle = ''' - //China - roots.push_back(World::Root()); - roots.back().identity = Identity("{}");'''.format(moon["roots"][0]["identity"]) - - for i in moon["roots"][0]["stableEndpoints"]: - middle += '\n roots.back().stableEndpoints.push_back(InetAddress("{}"));'.format(i) - - with open("mkworld.cpp", "r") as cpp: - code = "".join(cpp.readlines()) - - with open("mknewworld.cpp", "w+") as cpp: - code = code.replace(" //__PATCH_REPLACE__", middle) - print(code) - cpp.write(code) - - -if __name__ == '__main__': - patch_moon() - patch_world() +import os +import json +from re import M + + +def get_moon(): + with open("/var/lib/zerotier-one/moon.json", "r") as f: + moon = json.load(f) + return moon + + +def get_patch(): + with open("/opt/patch/patch.json", "r") as f: + return json.load(f) + + +def patch(): + moon = get_moon() + patch = get_patch() + + identity = moon["roots"][0]["identity"] + moon["roots"][0]["stableEndpoints"] = patch["stableEndpoints"] + + # 修改moon + with open("/var/lib/zerotier-one/moon.json", "w") as f: + f.write(json.dumps(moon,sort_keys=True, indent=2)) + + print("修改后的moon") + print(moon) + + # 修改world + moon["roots"][0]["stableEndpoints"] = get_patch()["stableEndpoints"] + text = f"""// Los Angeles + roots.push_back(World::Root()); + roots.back().identity = Identity("{identity}"); +""" + + for i in get_patch()["stableEndpoints"]: + text += f'\n roots.back().stableEndpoints.push_back(InetAddress("{i}"));' + + # 生成文件 + with open("/opt/patch/mkworld.cpp", "r") as cpp: + world = "".join(cpp.readlines()) + world = world.replace("//__PATCH_REPLACE__", text) + + with open("/opt/ZeroTierOne/attic/world/mkworld.cpp", "w") as cpp: + cpp.write(world) + + +if __name__ == '__main__': + patch() diff --git a/server.sh b/server.sh deleted file mode 100644 index 0060a73..0000000 --- a/server.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -echo "开始执行" -zerotier-one -d - -cd /opt/ztncui/src -npm start diff --git a/win_planet_ok.png b/win_planet_ok.png new file mode 100644 index 0000000..fdd6b85 Binary files /dev/null and b/win_planet_ok.png differ