群晖 docker ZeroTier方案
zerotier
这里要简单提一下 UDP 打洞的原理,UDP 打洞的本质是让 NAT 后面的机器 A 和 B 先连接一个有公网 IP 的中间服务器,然后中间服务器经过一番操作之后让 A 和 B 直接互联,这样之后的数据传输就是 A 和 B 之间直接传输,不再通过中间服务器。
但是出于节省资源和增强健壮性的角度,A 和 B 服务器直接打出来的「洞」并不是永久的,而是维持一段时间后释放,下次连接时重新打洞。这样就带来一个问题,Zerotier 是一款国外的项目,他提供的中间服务器到大陆的网络状况并不好,有很高的延迟,并且很可能丢包,这就导致我们每次「打洞」都有很高的延迟。
以我的网络环境进行的测试中,第一次「打洞」有接近 500ms 的延迟,之后延迟降低到 100ms 以下,直到这个「洞」被释放。
为了解决这个问题,Zerotier 提供了一个 moons 的概念,官方文档中提供了详细的解释和配置方法。
这篇博客文章提供了一份中文的教程,有兴趣的读者可以按此操作。
我的中间服务器部署在腾讯云,对三网都有良好的延迟和极低的丢包,因此在部署成功后,「打洞」的第一个数据包延迟降低到了不到 200ms,同时由于丢包较低,打洞成功率也有所上升。
教程
注册账号
之后去网络管理页面创建一个网络并记住 NetworkID。
网络管理界面可以配置很多东西,但是这里只介绍需要用到的部分,就是 NetworkID 和下面的 Members。
NetworkID 是在连入新设备时需要用到的标识符,每个设备连接这个虚拟的局域网时都要输入这个 ID。
Members 则是连入网络的设备列表,按照默认的设定,当有一个新设备接入网络时,用户需要在这个页面进行授权。
服务端安装:
curl -s https://install.zerotier.com | sudo bash #一键安装
systemctl enable zerotier-one #记得配置开机启动
zerotier-cli join <network id> #上面截图的
国内服务器搭建一个moon服务器
cd /var/lib/zerotier-one
zerotier-idtool initmoon identity.public > moon.json
zerotier-idtool genmoon moon.json
mkdir /var/lib/zerotier-one/moons.d
mv 000000xxxx.moon /var/lib/zerotier-one/moons.d/000000xxxx.moon
systemctl restart zerotier-one
NAS安装
创建一个持久的 TUN
insmod /lib/modules/tun.ko
2、测试tun.ko模块是否有效:依次输入以下命令:
1)mkdir /dev/net
2)mknod /dev/net/tun c 10 200
3) chmod 600 /dev/net/tun
4) cat /dev/net/tun
如果cat命令的返回结果是File descriptor in bad state,则表示模块已正确安装。
#编写脚本到路径: /usr/local/etc/rc.d/tun.sh 这将使得 /dev/net/tun 在启动时调用
echo -e '#!/bin/sh -e \ninsmod /lib/modules/tun.ko' > /usr/local/etc/rc.d/tun.sh
#给这段脚本添加权限
chmod a+x /usr/local/etc/rc.d/tun.sh
#运行脚本
/usr/local/etc/rc.d/tun.sh
#检查TUN的运行状态(输出“/dev/net/tun”)
ls /dev/net/tun
群晖 docker 镜像下载
创建zerotier容器,并启动
docker run \
-d \
--restart=always \
--name zerotier-one \
--device=/dev/net/tun \
--net=host \
--cap-add=NET_ADMIN \
--cap-add=SYS_ADMIN \
-v /volume1/docker/zerotier-one:/var/lib/zerotier-one \
zerotier/zerotier
配置ZeroTier网络信息:
docker exec -it 2da zerotier-cli status #查看状态
docker exec -it 2da zerotier-cli join db64858fed8a5da0 #加入网络
docker exec -it 2da zerotier-cli orbit 9d153e5b7c 9d153e5b7c#使用moon服务,地址为Members-Address
docker exec -it 2da zerotier-cli listpeers #检查是否加入moon
docker exec -it 2da zerotier-cli listnetworks #查看配置情况
增加路由
其中 192.168.XXX.0/24 需要修改为zerotier网站上设置的本局域网的IP地址:172.29.0.0/16
#!/bin/bash
echo `date -d today +"%Y-%m-%d %T.%N"` " Add route start......"
#判断docker是否启动,标志是通过ip a命令查看特有设备标志zt7abcd2sa,各个机器不同。
dkstart=`ip a |grep zt7abcd2sa`
while [$dkstart -eq ""]
do
#如果不存在,那么就等待60秒后再判断。
echo `date -d today +"%Y-%m-%d %T.%N"` " Docker is not exist, waiting 60s."
sleep 60
dkstart=`ip a |grep zt7abcd2sa`
done
#循环出来,说明docker已经启动。判断路由是否存在。
resultstr=`route -n |grep zt7abcd2sa`
blankstr=""
if [$resultstr -eq $blankstr]
then
echo `date -d today +"%Y-%m-%d %T.%N"` " Route is not exist, we will add route!"
#增加路由命令
route add -net 10.147.88.0/24 dev zt7abcd2sa
sleep 3
#等待3秒后判断是否增加成功
resultstr=`route -n |grep zt7abcd2sa`
if [$resultstr -eq $blankstr]
then
echo `date -d today +"%Y-%m-%d %T.%N"` " Add route failed!"
else
echo `date -d today +"%Y-%m-%d %T.%N"` " Add route success! The route info is: "$resultstr
fi
else
echo `date -d today +"%Y-%m-%d %T.%N"` " Route is exist. The route info is: "$resultstr
fi
echo `date -d today +"%Y-%m-%d %T.%N"` " Add route end!"
生成的脚本需要增加执行权限,通过命令修改:chmod +x zerotier_addroute.sh ,修改后脚本为绿色。
增加计划任务:
控制面板->任务计划->新增->触发的任务->用户定义的脚本。
用户定义脚本中,加入之前编辑的脚本,并将打印日志写入日志文件。
bash /usr/local/zerotier_addroute.sh >>/usr/local/addroute.log
并在任务计划中勾选“已启动->保存”
在docker创建zerotier实例时,主要要将“启用自动重新启动”选上。
测试:
可在控制面板,计划任务中,选中刚才自定义的计划任务,点“运行”,运行一次脚本,并在telnet后台查看运行日志是否正常运行。日志存放在/usr/local/目录下。
查看命令:tail /usr/local/addroute.log
PC:
https://www.zerotier.com/download/cd C:\Program Files (x86)\ZeroTier\One #按照文件夹 ,自己找
zerotier-cli.bat orbit [节点ID地址] [节点ID地址]
zerotier-cli.bat listpeers