玩一下 zerotier

之前咱玩过 frp,主要用于远程操作家里的电脑。这东西方便是方便,但用了一段时间看了看日志,好家伙被扫了几百遍。。。。毕竟对外就一个端口一个密码,实话说,不太安全(前几个月还看见 v2ex 因为 frp 导致公司电脑被勒索,后面不知道咋样了)。

类似的工具,纯粹的 ddns 类工具效果和 frp 一样;wireguard 之类的工具,倒是需要先通过工具连进对等网络才能去链接 rdp 等服务,安全了不少,但缺点是要配置分流;最后我看中了 zerotier,也是需要先通过工具连进对等网络,不过不用配置分流,也有网页端 ui 方便配置,还可以软件本身提供的中心节点,速度慢可以靠自建的 moon 中继节点加速,不太好的地方就是开源不完全,以及另外俩待会我会提到的缺点。都还可以接受,暂时用着呗。

步骤就偷懒记简略点。

入门

参考文章:ZeroTier 内网穿透 - Yogile - 博客园

大部分应用场景都是我用手机(安卓)/ 轻薄本连回家中的游戏本,所以先尝试把他们连起来。

下载

安卓端直接通过 google play 下载同名应用。

windows 可以通过官网下载安装,不过这玩意 chocolatey 里面也有,直接省事一个命令下去:

1
choco install zerotier-one -y

配置

zerotier 首页注册登录,创建网络(Create a Network)。

在 Managed Routes 中,按自己的喜好设置一个网段(CIDR 格式,也就是 x.x.x.x/24 这样),待会自己设备可以分配到位于这个网段内的地址。

剩下的就可以不管了,好奇的话可以看参考文章。

加入

有两种方法。

  1. 将客户端中的 nodeid 填入 web 端的 Manually Add Member 中;
  2. 使用客户端的 Join Network 功能,将 web 端的 Network ID 填入。

把手机和游戏本都 join 进来以后,在 web 端里面就能看到它们了。把最左边的勾打上,修改一下 ip 方便记忆。

(21.5.22 更新) 把 ipad 也加进来了,但和 android/pc 秒开秒认证不同,ios 我足足开着十来分钟下面的 web 才有认证设备出现(此时屏幕右上角 vpn 图标不出现),认证完再开等了半分钟 vpn 图标才出来,emmm。。。看商店里面,自 4 月份开始的四五条评论都给了 ios 版一星,原因都是获取不到 ip,这应该是个 bug。

使用

此时 pc 和安卓同时启用客户端,web 这边的 last seen 就会显示 online(像上图一样)。打开安卓的 rdp 客户端,通过刚刚我们修改的 pc 端的 ip(以上图为例,假设下面那一个是 pc 的客户端,没修改 ip 的话,pc 在 zerotier 内网中 ip 就为 10.10.10.181,把这个 ip 输入到 rdp 的地址栏中)。

如果我没猜错的话。。。应该连不上~

这就是 zerotier 的缺点之一,连上 vpn 后,要过一会才能成功建立链接,这个时间或长或短,应该得要几分钟。几分钟后,再次链接,应该就能上了。如果还不能上,关闭 windows 的防火墙,尝试用 termux ping 一下 10.10.10.181,排查一下是 zerotier 的问题还是自己配置的问题。

通过路由(ac86u)转发

相比于让 pc 把所有端口全都交出去,我更希望通过路由器只把我想要放到外网的端口透出去。本节只适用于 merlin 和 merlin 改,官改未知,原厂肯定 8 行。

参考文章:

安装 zerotier

安装 opkg

拿个 u 盘 / tf 卡插路由器上,进入 ssh,输入

1
entware-setup.sh

根据提示,安装 opkg。

然后安装 zerotier

1
2
opkg update
opkg install zerotier

加入

启用 tun

1
modprobe tun

启动 zerotier

1
zerotier-one -d

仍旧是两种加入方法,一种是获取 nodeid,填到 web 中

1
zerotier-cli info

另一种是直接在客户端通过 Network ID 加入

1
zerotier-cli join <your network id>

配置防火墙

看一眼自己路由器 INPUT 里有几条规则

1
iptables -v -L INPUT -n --line-numbers

16 条,很好。于是我们下面命令 INPUT 后面这个数字就设为 17。

1
iptables -I INPUT 17 -i zt+ -j ACCEPT

配置完记得用前一条命令确认一下。

新建 S90zerotier-one.sh

1
nano /opt/etc/init.d/S90zerotier-one.sh

内容为

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
#! /bin/sh

case "$1" in
start)
if lsmod | grep -q tun ;
then echo "mod tun ready" ;
else
modprobe tun;
logger -t "zerotier" -c "modprobe tun started, zerotier-one should start in one minute" -p user.notice ;
exit 0;
fi
if ( pidof zerotier-one )
then echo "ZeroTier-One is already running."
else
echo "Starting ZeroTier-One" ;
/opt/bin/zerotier-one -d ;
echo "$(date) ZeroTier-One Started" | logger -t "zerotier" -c "Started" -p user.notice ; #>> /opt/var/log/zerotier-one.log ;
fi
;;
stop)
if ( pidof zerotier-one )
then
echo "Stopping ZeroTier-One";
killall zerotier-one
echo "$(date) ZeroTier-One Stopped" | logger -t "zerotier" -c "Stopped" -p user.notice ; #>> /opt/var/log/zerotier-one.log
else
echo "ZeroTier-One was not running" ;
fi
;;
status)
if ( pidof zerotier-one )
then echo "ZeroTier-One is running."
else echo "ZeroTier-One is NOT running"
fi
;;
*)
echo "Usage: /etc/init.d/zerotier-one {start|stop|status}"
exit 1
;;
esac
exit 0

给上权限

1
chmod +x /opt/etc/init.d/S90zerotier-one.sh

然后用这个刚写的脚本重启 zerotier

1
2
/opt/etc/init.d/S90zerotier-one.sh stop
zerotier-one -d

配置端口透穿

1
iptables -t nat -A PREROUTING -d [路由器在zerotierweb中的ip] -p tcp --dport [透穿的端口] -j DNAT --to-destination [透穿服务所在设备的内网ip]:[透穿的服务的内网端口]

打个比方:在 web 端中我们设置路由的 zerotier 局域网 ip 为 10.10.10.150;pc 通过 ipconfig 命令获取到自己的内网 ip 为 192.168.1.2,要透穿出去的服务是 rdp,所以内网端口为 3389;为了安全,透到外网的端口不用 3389 而是 4389,则:

1
iptables -t nat -A PREROUTING -d 10.10.10.150 -p tcp --dport 4389 -j DNAT --to-destination 192.168.1.2:3389

如果要透穿出去的内网端口无需和外网端口不一致,那么可以同时透穿多个端口。举个例子,如果你用 teamviewer 提供的默认隧道来远程操纵,这玩意平日里就会整天弹仅用于非商业用途的提示,有时候还会提醒你只能用 x 分钟就强制下线。改为仅在内网提供远程服务器的 lan 模式,隧道通过 zerotier 进行转发连接,就一切正常。teamviewer 只支持使用 5938 端口,不像 rdp 地址栏里面跟个新端口号就算改端口了;同时 teamviewer 在某些情况下还会走 443 和 80 端口,所以这两个端口最好也开放出来。

1
iptables -t nat -A PREROUTING -d 10.10.10.150 -p tcp --m multiport --dport 5938,443,80 -j DNAT --to-destination 192.168.1.2

什么你说有了 rdp 为什么还要用 teamviewer?那我就偏个题:

  • teamviewer 除非安装它提供的驱动或者你关闭物理显示器,否则远控的时候屏幕是亮着的;rdp 需要通过微软账户访问,除非你电脑里还有其他账号(而且你远控过来多半还是要操作你原来账号的内容),否则电脑屏幕是黑着的。
  • 因此,远控的时候如果放个视频什么的,被远控的 teamviewer 设备也会发出声音,rdp 设备就不会。
  • rdp 远控不支持使用独显,teamviewer 支持。

另外,如果先使用 rdp 远控,后续没有回到实机解锁就用 teamviewer 远控,那么 teamviewer 远控时会看到密码输入界面,输入密码后会黑屏。此时按一下 WIN+L 就会恢复正常,不想单独开篇文章记了,就放在这里吧。


配置完确认一下

1
iptables -n -t nat -L PREROUTING --line-numbers

此时用手机 rdp 通过 10.10.10.150:4389 应该就能访问过来了。(同样开开 zerotier 后要等几分钟)

配置自启

编辑文件 /jffs/scripts/nat-start

1
nano /jffs/scripts/nat-start

加入

1
modprobe tun

编辑文件 /jffs/scripts/wan-start

1
nano /jffs/scripts/wan-start

加入

1
cru a ZeroTierDaemon "* * * * * /opt/etc/init.d/S90zerotier-one.sh start"

新建文件 /jffs/scripts/firewall-start

1
nano /jffs/scripts/firewall-start

内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh
logger -t "custom iptables" "Enter" -p user.notice
iptables -C INPUT -i zt+ -j ACCEPT
if [ $? != 0 ]; then
iptables -I INPUT -i zt+ -j ACCEPT
#需修改
iptables -t nat -A PREROUTING -d 10.10.10.150 -p tcp --dport 4389 -j DNAT --to-destination 192.168.1.2:3389
iptables -t nat -A PREROUTING -d 10.10.10.150 -p tcp --m multiport --dport 5938,443,80 -j DNAT --to-destination 192.168.1.2
#修改到此
logger -t "custom iptables" "rules added" -p user.notice
else
logger -t "custom iptables" "rules existed skip" -p user.notice
fi

标注为需修改到修改到此的中间两句,按使用者个人需求进行替换,在上面配置防火墙 -> 配置端口透穿中,写了多少句,就加多少句进来。

检查

配置完直接重启检查。通过

1
2
iptables -v -L INPUT -n --line-numbers
iptables -n -t nat -L PREROUTING --line-numbers

若是出现了 zt+ 接口和端口透穿相关语句,且

1
zerotier-cli info

显示正常启用,则配置成功。

(23.5.12 更新)通过路由(ac86u)在 koolshare 商店中安装并远程唤醒

因为远程控制有更好用的 tailscale 了。但 headscale 在 ac86u 上不受支持非常不稳定,比较有用的远程唤醒还是需要 zerotier 来实现。但现在软件商店中有了 zerotier 后,不需要再进行那么多复杂的步骤了。

  1. 进入 koolshare 商店,安装 zerotier。

  2. 安装后根据插件提示连接并开启 zerotier。

  3. 将电脑/设备接上有线路由,并打开幻数据包唤醒功能。

  4. 手机/电脑在外网连接 zerotier,通过路由器这边连接的 ip 进入 merlin 的管理页面,找到网络工具->通过网络(LAN)唤醒,定位到相应的 mac(常用的 mac 可以通过加号添加到底下),点击下面的超链接,mac 会显示目标栏的框框里,然后点击唤醒,这时候电脑应该就能正常开机了。

  5. 插件如果在路由正常关机和正常重启(通过 webui 重启),重启后应该是会自动启动的。但如果用 ssh 的 reboot 命令重启路由,重启后 zerotier 插件可能不会正常启动,需要手动启动。

配置 moon 节点

参考文章:

安装 zerotier 并加入节点

我这边装 moon 节点的 vps 系统是 debian,apt 仓库里没有 zerotier。得用 zerotier 官网的官方脚本:

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

默认安装后即启动 zerotier,下面这句命令会报错。不过为了防止万一 zerotier 没启动,还是运行一遍为好

1
zerotier-one -d

加入方法不再赘述。

配置 moon 节点

进入 zerotier 配置文件目录。

1
cd /var/lib/zerotier-one

生成 moon.json 签名文件。

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

编辑

1
nano moon.json

修改 stableEndpoints,在里面填上一个 CIDR 地址,比如(如果有 ipv6 需求可看参考文章进行修改)

1
"stableEndpoints": ["1.2.3.4/9993"]

另外,记下此处 id 的值。

生成 moon 签名文件

1
zerotier-idtool genmoon moon.json

如无意外会显示:

1
wrote xxx.moon (signed world with timestamp xxx)

将文件考入 moon 节点文件夹中

1
2
3
mkdir /var/lib/zerotier-one/moons.d
cp *.moon moons.d/
rm *.moon

重启服务

1
service zerotier-one restart 

即可。

连结 moon 节点

在其他节点(非 moon 节点)使用命令

1
zerotier-cli orbit [moonID] [moonID]

moonID 是上面让记过的那个。另外,这里的确是输入两遍 moonID,你没有看错。。。

再输入

1
zerotier-cli listpeers

发现多了一个行末为 moon 结尾的行即成功。

另一个方法是把刚刚获得的 moon 文件考下来放入指定目录,且据说这个方法相对输入命令的方法有一个好处,若是 planet 节点崩掉(虽然可能性很小),通过 moon 节点仍能维持正常工作,输入命令那个方法就不行。但 ac86u 里没有放这个文件的地方,所以我没做尝试。

其他注意事项

  1. 如果 moon 节点更换了 zerotier ip,在通过 zerotier-cli listpeers 会发现 moon 节点 ip 缺失。有可能要重新生成 moon 文件,或者停止 zerotier 服务后过若干分钟再启动即可解决。

  2. 另一个,也是 zerotier 目前最大的缺点:安卓不支持使用 moon 节点。apk 没有这个功能,也没有目录放置 moon 节点文件的地方。改用二进制文件呢?发现 termux 没有渠道来安装 zerotier(各个库中没有,官网的安装脚本不支持),手工编译报错:

    且 issue 中有同样的问题:ZeroTierOne/node at master · zerotier/ZeroTierOne

    维护者表示我们不支持除了 apk 以外的安卓使用方法。

    没辙,差评.jpg