前言
在外面的时候可能会需要连接家里放的树莓派、智能路由器(Openwrt)、NAS 等设备,但是家里的网络一般没有公网 IP 不能直接连接,这时候就需要使用各种内网穿透的方法连接家中的设备。
简介
常见的内网穿透方法有 OpenVPN、 FRP、Ngrok 等,这些方案一般需要一个有公网 IP 的 VPS 做反向代理进行内网穿透连接,连接的速度取决于做中转代理的 VPS 的最大带宽。
这里介绍另外一款免费的、可拓展的、功能强大的内网穿透工具ZeroTier。
ZeroTier is a smart Ethernet switch for planet Earth.
ZeroTier通过多个根服务器帮助我们建立虚拟的局域网,让虚拟局域网内的各台设备可以打洞直连。
这些根服务器的功能类似于通过域名查询找到服务器地址的DNS服务器,它们被称为行星(Planet)。
使用官方服务
如果只想简单的使用ZeroTier,不想折腾,可以直接使用官方提供的服务。
在官网注册一个账号,登陆账号配置好自己的虚拟局域网,然后下载安装客户端让设备完成组网即可。
使用官方的服务有几个问题:
- 免费账户有组网上限,只允许100台设备进行组网
- 官方行星服务器部署在国外,国内访问延迟很大,虚拟局域网不稳定,容易掉链子
为了解决上面的问题,需要私有化部署ZeroTier服务,搭建私有的行星(planet)服务器。
搭建私有化 ZeroTier
下面以在腾讯云服务器上部署作为例子,记录下搭建流程。
云服务器的系统是 CentOS 7.6.1810 x86_64(Py3.7.9)
。
安装编译组件
yum install wget gcc gcc-c++ git -y
yum install json-devel -y
安装官方客户端
curl -s https://install.zerotier.com/ | sudo bash
安装完成后,默认监听的端口是9993
,这个端口需要对外提供服务,需要在服务器防火墙和云服务提供商的安全组设置放行。
- 宝塔面板:安全->系统防火墙->输入9993,放行
- 腾讯云安全组:新增允许访问的规则
UDP:9993
和TCP:9993
获取必要信息
安装完成后,到安装目录/var/lib/zerotier-one/
中找到并记录identity.public
和authtoken.secret
文件里的字符串,备用。
注意:每台设备不同,字符串也不同,不要混用
。
identity.public
里的内容格式如下:
65379ff88e:0:161cd83965f056b2a1b8249bd92a7b6cb97b8dcc97808b0df1115f4af85f45474cbdc4353f77c4f033955596b30a596fc493efdb81667622b458ddf8c361c028
authtoken.secret
里的内容格式如下:
w8cl25tzb38dvwffenucrbug
下载源码
直接使用 git 拉取源码,我使用的是1.10.0
版本:
git clone https://github.com/zerotier/ZeroTierOne
由于国内服务器对github
访问有限制,可以将源码镜像到gitee
,然后在拉取。
另一种简单粗暴,直接下载压缩包然后再上传到服务器解压到ZeroTierOne
。
修改源码
找到ZeroTierOne/attic/world/mkworld.cpp
并打开,仿照mkworld.cpp
原来的代码,将我们自定义的Planet
服务器添加进去。
注意,需要删除或注释掉至少一个原来的Planet
服务器,再增加我们自己的服务器,否则后续执行我们编译的可执行程序时程序会崩溃。
原因是代码里默认只允许4台Planet
服务器,可以在World.hpp
里看到如下定义#define ZT_WORLD_MAX_ROOTS 4
。
改后的文件部分内容如下:
// =========================================================================
// EDIT BELOW HERE
std::vector<World::Root> roots;
const uint64_t id = ZT_WORLD_ID_EARTH;
const uint64_t ts = 1567191349589ULL; // August 30th, 2019
// h4ck1n
roots.push_back(World::Root());
roots.back().identity = Identity("填写identity.public里的字符串");
roots.back().stableEndpoints.push_back(InetAddress("服务器ip地址/通讯端口")); // 默认端口是9993,可以自行修改,但不建议
// 下面这些是官方的根服务器,可以注释或删掉,如果想保留一些官方的根服务器,只需要删除或注释掉一个就行
// 这里注释掉最后一个根服务器,然后增加一个自己的
// Los Angeles
roots.push_back(World::Root());
roots.back().identity = Identity("3a46f1bf30:0:76e66fab33e28549a62ee2064d1843273c2c300ba45c3f20bef02dbad225723bb59a9bb4b13535730961aeecf5a163ace477cceb0727025b99ac14a5166a09a3");
roots.back().stableEndpoints.push_back(InetAddress("185.180.13.82/9993"));
roots.back().stableEndpoints.push_back(InetAddress("2a02:6ea0:c815::/9993"));
// Miami
roots.push_back(World::Root());
roots.back().identity = Identity("de8950a8b2:0:1b3ada8251b91b6b6fa6535b8c7e2460918f4f729abdec97d3c7f3796868fb02f0de0b0ee554b2d59fc3524743eebfcf5315e790ed6d92db5bd10c28c09b40ef");
roots.back().stableEndpoints.push_back(InetAddress("207.246.73.245/443"));
roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:9002:5cb:ec4:7aff:fe8f:69d9/443"));
// Tokyo
roots.push_back(World::Root());
roots.back().identity = Identity("34e0a5e174:0:93efb50934788f856d5cfb9ca5be88e85b40965586b75befac900df77352c145a1ba7007569d37c77bfe52c0999f3bdc67a47a4a6000b720a883ce47aa2fb7f8");
roots.back().stableEndpoints.push_back(InetAddress("147.75.92.2/443"));
roots.back().stableEndpoints.push_back(InetAddress("2604:1380:3000:7100::1/443"));
// Amsterdam
// roots.push_back(World::Root());
// roots.back().identity = Identity("992fcf1db7:0:206ed59350b31916f749a1f85dffb3a8787dcbf83b8c6e9448d4e3ea0e3369301be716c3609344a9d1533850fb4460c50af43322bcfc8e13d3301a1f1003ceb6");
// roots.back().stableEndpoints.push_back(InetAddress("195.181.173.159/443"));
// roots.back().stableEndpoints.push_back(InetAddress("2a02:6ea0:c024::/443"));
编译配置文件
cd ./ZeroTierOne/attic/world/
source ./build.sh
./mkworld
mv ./world.bin ./planet
替换配置文件
为了让服务端和客户端都使用我们自定义的服务器,需要使用生成的planet
文件替换服务器和客户端的对应文件,各平台的路径如下:
Linux: /var/lib/zerotier-one
FreeBSD/OpenBSD: /var/db/zerotier-one
Mac: /Library/Application Support/ZeroTier/One
Windows: \ProgramData\ZeroTier\One
(That's the default. The base 'shared app data' folder might be different if Windows is installed with a non-standard drive letter assignment or layout.)
因此,在服务端执行命令:
cp -r ./planet /var/lib/zerotier-one/
cp -r ./planet /root # 备用
重启服务端
systemctl restart zerotier-one.service
安装管理面板
为了管理设备,需要安装后台管理面板,管理面板有很多,这里使用 ztncui。
sudo yum install https://download.key-networks.com/el7/ztncui/1/ztncui-release-1-1.noarch.rpm -y
sudo yum install ztncui -y
sudo sh -c "echo 'ZT_TOKEN=authtoken.secret文件里的字符串' >> /opt/key-networks/ztncui/.env"
sudo sh -c "echo 'NODE_ENV=production' >> /opt/key-networks/ztncui/.env"
sudo sh -c "echo 'ZT_ADDR=127.0.0.1:9993' >> /opt/key-networks/ztncui/.env" # 面板与本地服务的通讯端口,没有自定义端口的话使用9993就行,否则需要和自定义的端口一致
sudo systemctl restart ztncui
更多配置信息,可以查看 README.md。
访问管理面板
安装后,默认监听localhost:3000
端口,如果要支持外网访问,需要启用反向代理。
宝塔面板配置反代方法:
- 域名解析:确保域名已经解析到你的服务器ip
- 新建站点:打开宝塔->网站->添加站点
- 设置反代:宝塔->网站->点击域名->反向代理,目标URL填写
http://127.0.0.1:3000
,然后确定
因为安全原因,不建议开放外外网访问,毕竟所有组网设备都连接在一个局域网,风险比较高,而且管理面板使用的频率也不高。
这里使用SSH本地端口转发来将远程服务映射到本地,然后在本机访问。
执行命令:
ssh -p PORT root@服务器IP -L 127.0.0.1:3000:127.0.0.1:3000
现在可以在本机上访问http://127.0.0.1:3000
来使用控制面板。
面板的默认账号和密码是admin/password
,第一次登录需要改密码,改完密码后在页面上点注销,然后用新密码登录。
创建私有网络
登陆面板以后,点击add a network
建立一个虚拟网路,network name
网络名称随便填,最后按create a network
按钮保存。
页面上的there are no members on this network - users are invited to join xxxxxxx
这里的xxxxxxx
是网络ID,需要记下方便其他电脑加入。
点击上方的Easy Setup
对网络进行其他配置。
客户端组网
这里以 macOS 为例,其他系统类似。
安装官方客户端,各平台客户端下载地址。
或者使用brew cask
进行安装:
brew cask install zerotier-one
下载服务器上/root
目录下备份的planet
文件,替换掉/Library/Application Support/ZeroTier/One/planet
文件。
注意,
Android
和iOS
客户端不存在planet
文件,无法简单替换,需要特殊处理,比如静态分析后PATCH。
针对iOS客户端,我写了一个简单的Tweak,代码在这ZeroTieriOSFix,Android版本自行搜索。
经评论区网友帅帅的南山
提醒,Android和iOS平台也是存在planet
文件,文件路径藏得比较深,文章末尾会补充说明。
重启服务:
sudo launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist
sudo launchctl load /Library/LaunchDaemons/com.zerotier.one.plist
打开刚刚安装的ZeroTier
应用,在菜单栏上会出现一个图标,点击图标,选择Join New Network...
,填入之前新建的网络ID,确认。
登陆管理后台,在Members
列表会出现一个新设备,选择它,给设备一个名字,然后勾选Authorized
。
查看客户端网络状态,如果显示OK
,表示组网成功,之后就可以使用管理后台显示的局域网IP对指定设备进行访问。
iOS 客户端
原本以为iOS客户端不存在planet
文件,经网友帅帅的南上
提醒并验证了下,确实存在planet
文件,只是位置比较隐蔽。
路径可以通过Filza
管理器来查找,打开Filza
管理器,进到/var/mobile/Containers/Data/PluginKitPlugin
目录,点击左上方搜索,输入ZeroTierPTP
,如图:
点击进入,就可以看到心心念念的planet
文件,替换它。
需要注意:
- 不论是使用上面的方法还是安装
Tweak
,都需要设备越狱。 - 替换后需要注意确保新的
planet
文件权限为mobile:mobile
。 - 如果没有找到上述的目录或者文件,请尝试先打开运行一次
ZeroTier One
应用。
Android 客户端
安卓端方法也是由帅帅的南山
提供,本人没有安卓设备,因此未验证。
Android端的planet
文件路径为:
generic_x86_64_arm64:/data/data/net.kaaass.zerotierfix/files # ls -l
total 40
-rw-rw---- 1 u0_a170 u0_a170 141 2023-06-03 16:51 identity.public
-rw-rw---- 1 u0_a170 u0_a170 270 2023-06-03 16:51 identity.secret
drwx------ 2 u0_a170 u0_a170 4096 2023-06-03 16:51 networks.d
drwx------ 2 u0_a170 u0_a170 4096 2023-06-03 16:51 peers.d
-rw-rw---- 1 u0_a170 u0_a170 570 2023-06-03 16:51 planet
generic_x86_64_arm64:/data/data/net.kaaass.zerotierfix/files #
替换了目录里面的planet
文件即可。
需要注意,安卓设备可能需要root之后才能有权限进行操作。
参考
本文为原创文章,版权归字节时代所有,欢迎分享本文,转载请保留出处!
大侠求教,一步步照着来,OPENWRT加了这个能看到。但电脑加了,就是在后台members看不到这个设备。也不知道哪里错了,
@wwj看不到这个设备基本上是因为planet文件替换不正确或者替换后服务没重启,既然OPENWRT系统OK,说明服务器配置应该是没问题的。
Error retrieving list of networks on this controller: HTTPError: Response code 401 (Unauthorized)
试了好几遍一直出现这个问题。。
@stl什么时候出现这个提示,是否在控制面板给新接入的设备授权了?
大佬,关于ios 的Tweak我不理解是什么意思,虽然我已经越狱也替换了Tweak.x中的代码,但是我不清楚下一步应该怎么办。
@西瓜电脑安装theos环境,然后编译项目,把生成的deb文件使用爱思助手之类的放到手机里,ssh到手机,执行"dpkg -i 你的deb文件路径"安装deb。安装完成后,打开 ZeroTier One,输入你自己搭建的服务器的网络ID,进行连接即可,连接的时候会提示使用VPN,允许就行了。
如果你还不知道什么是tweak和theos,建议搜索学习一下再折腾。
ios系统也有planet文件
@帅帅的南山666,藏这么深都被你发现了,我没试过,有兴趣的可以替换掉这个planet是否可行。
@h4ck1n已经测试 替换后可用
@帅帅的南山6到飞起,文章我也更新一下。
@h4ck1nzerotierfix安卓端目录 app也可以直接导入
generic_x86_64_arm64:/data/data/net.kaaass.zerotierfix/files # ls -l
total 40
-rw-rw---- 1 u0_a170 u0_a170 141 2023-06-03 16:51 identity.public
-rw-rw---- 1 u0_a170 u0_a170 270 2023-06-03 16:51 identity.secret
drwx------ 2 u0_a170 u0_a170 4096 2023-06-03 16:51 networks.d
drwx------ 2 u0_a170 u0_a170 4096 2023-06-03 16:51 peers.d
-rw-rw---- 1 u0_a170 u0_a170 570 2023-06-03 16:51 planet
generic_x86_64_arm64:/data/data/net.kaaass.zerotierfix/files #
@h4ck1nios端估计也可以支持moon 直接把moon.d文件夹复制进去
@帅帅的南山恩,后来人可以一试。
想问下,iOS不越狱,能否修改Planet文件?
@iOS小菜鸡目前已知的方法在文章已经有介绍,都需要越狱。不越狱的情况下,如果你能解决不使用越狱环境就无法hook函数的问题(比如静态patch二进制文件),理论上未越狱也是可以。
@iOS小菜鸡请教大佬,Failed to start ztncui - ZeroTier network controller user interface.一直无法启动怎么办
@学者zero什么时候?
@h4ck1n解决了,只能用Ubuntu,CentOS启动服务的时候死活上不来
ios的用巨魔装的,替换了planet文件,还是会显示6023
@袁大慈6023是什么错误,没遇到过,如果替换文件成功,应该是没问题的,替换后要重启下应用。