ZeroTier 组网小记 - 路由器 NAT 配置

11,442 阅读9分钟

📌 背景

学校最近在改造网络,本来应该是好事情,但是最近发现学校网没办法连回寝室了,不晓得搞的什么名堂,明明寝室宽带有公网 IP 但是在校园网就是连不上,反正给快把我搞自闭了。
为何这样说呢?因为我这边开发基本上都是 Remote Develop,需要远程连回寝室才能开发的,这样的好处就是不言而喻,基本上不用担心笔记本用电和环境问题。
但是学校这波操作直接把我打回原形,让我深刻认清现实,不由赞叹感慨万千。虽然有 frps 的备用方案,但是这个方案根本不是用来开发的,只是用来应应急而已。要想稳定使用,翻来翻去还是 ZeroTier 最适合不过了。

🌚 尝试过的方案

为了说清楚我为啥最后选了 ZeroTier,我得说一说我了解的其它方案。对了,我选择的时候不知不觉有一个原则:**付费订阅方案 -- 直接放弃。**没办法我只是一个贫穷可怜的学生,没办法 afford 这些企业级的服务,毕竟钱到位了,还要考虑这些乱七八糟的事情嘛?直接整套私人托管的服务器不香嘛?

  • NGROK

记得当时 v1 版本还是开源的呢!后面搞起商业化了。因为是服务端配置,比较方便搞 Web 管理后台,自然是适合为收取订阅费用。当时比较无知,花了 10 元用了一个月,后面再也没有用过了。

  • DDNSTO

最早是在梅林的软件中心里遇见的,宝哥开发(非常厉害)。作为一个路由器插件真的是非常简单易用,简直就是小白的福音。缺点也很明显,需要微信认证之后才能打开自己创建的服务,而且被限制在浏览器里面,要知道浏览器做的再好也比不过用了多年的 xshell 舒服,也因此不支持 vscode remote develop。最近体验了一下就放弃了,因为需要付费订阅才能使用了 👋。

  • FRP

从当初的 1.x 版本就开始使用了,当时 frp 好像还不太行,没有许多路由器的插件支持啊。现在就不一样了,插件都很完善了,而且 Github 的小星星都来达到 47k 了,可见其流行程度。这也是我从一开始就用到现在的方案,而且有许多的特效,比如说支持点对点通道的建立(NAT 穿透),支持各种协议等。你只需要一台具有公网 IP 的服务器即可。不过受限于 1M 的宽带,对我只是当做应急备用措施。

  • SSH

SSH 有一个代理的功能,也可以实现穿透的效果,而且传输过程中自带加密,不过一般情况都是临时使用吧😂。

  • ZeroTier

感觉 ZeroTier 才代表了未来的方向,IPv6 据说可以做到万物互联,反正我现在根本没有智能设备也体验不到。那就先让我 IPv4 互联吧,ZeroTier 组建的虚拟内网才是真的实用,其它方案基本上都是对我提供一个端口罢了,其主打对我。而 ZeroTier 主打对内,所谓的“对外”如果只有你一个人在用其本质还是“对内”。既然这样,不如给笔记本装一个 ZeroTier 服务,这样无论走到哪都可以随时连回来。

  • 公网 IP

上面的方案都不可避免的需要公网 IP 的参与,如果你直接拨号后就是公网 IP,这不就是对上面方案的降维打击嘛?需要内网的服务?没问题,分分钟在路由器上创建一条端口转发规则即可,真的做到了走到哪连到哪的效果了。唯一的缺点恐怕就是变动的 IP 和不对称的上传速度了吧?

🔥 目标

如果只是简单的将两台装有 ZeroTier 的电脑打通,显然用不到这篇文章。因为我之前就是这样做的呢!但是问题多多,基本上没办法使用,为此折腾了一天的时间才折腾了一篇文章出来。

遇到的问题

  • 两台电脑的 ZeroTier 网络十分不理想,通过 iperf 测试速度只能达到 1M 左右,而且经常性断线,连接过程非常折磨人,尽管配置了个人 moon 服务器。
  • 经常丢包,丢包重传会导致 SSH 体验特别差劲。
  • 断线一次不知道什么时候能再次建立连接。

说了这么多,其根本原因就是学校的了色校园网络,呸。

解决办法

由于那两台电脑都没有公网 IP,因此 ZeroTier 的表现非常的差劲。经过测试,具有公网 IP 的路由器上 ZeroTier 的表现非常好,网络质量非常稳定。因此解决方法是通过路由器的转发来实现两台机器的互连。

🌈 具体需求

  • 路由器下面的设备不需要安装 ZeroTier 也能访问 ZeroTier 网络,并且需要分配一个 IP 地址,能被 ZeroTier 网络中任何节点访问到。


呃说了半天其实需求只有后面一半,因为前一半的需求已经在上一篇文章中实现了 😓。
使用 Google 找了一圈,只找到两篇相关文章。


其核心是:配置 ZeroTier 的路由,让某一网段通过 ZeroTier 网络中的一个节点转发。

  • 这个“网段”肯定不能和 ZeroTier 配置的网络重叠,否则会转发失败。
  • 这个“网段”不能是常见的“192.168.x.x”私有网段,否则和本地 192.168 网段重合会导致本地局域网不能互通。

上面两点需要特别注意,因为我没系统学习过网络相关的知识,这也是我踩了许多坑才得出的结论。

现在问题来了:一开始配置路由器的时候根本想不到“192.168.x.x”会遇到今天这样的问题。如果修改路由器的地址,其下面的所有设备都需要跟着做出相应的修改。这是一件吃力不讨好的事情,因为许多设备的地址都是静态的,而且修改起来非常的麻烦。总不可能为了这点破事情大动干戈吧。

后面我想,**为何不通一个网卡绑定多个 IP 地址呢?这样我只需要额外绑定另一个网段的 IP 地址就可以达到分配私有 IP 的目的了啊。**我现在开始后悔为何不好好看看鸟哥的书,因为路由相关的知识真的不太懂。尤其是 iptables 这块内容。哎,书到用时方恨少,💰到月底不够花。

debian 配置第二 IP 地址

  • 临时配置
ifconfig ens192:0 172.20.0.8 netmask 255.255.0.0 up
# ens192:0 后面的 0 可以是其它数字,说明可以配置很多 IP 地址哦

这里有个困惑,为何第二个 IP 地址不能配置第二个 gateway?
image.png

  • 永久配置
# /etc/network/interfaces

auto ens192
iface ens192 inet static

  address 192.168.1.8
  gateway 192.168.1.2
  netmask 255.255.255.0

auto ens192:0
iface ens192:0 inet static

 address 172.20.0.8
 netmask 255.255.255.0
 

这样配置完成后,重启后第二 IP 也不会丢失了。

检查一下路由表,发现根本没有变化
image.png

Windows 配置第二 IP 地址

为了随时随地使用远程桌面,给 Windows 也配置好。
image.png
不得不说,Windows 真的是一图胜千言啊,果然是图形操作系统的老大哥。

检查互通

配置好 172.20.0.0/24 网段后,需要检查测试一下。

# 172.20.0.8 虚拟机下面
# ~ ping 172.20.0.11
PING 172.20.0.11 (172.20.0.11) 56(84) bytes of data.
64 bytes from 172.20.0.11: icmp_seq=1 ttl=128 time=0.259 ms
64 bytes from 172.20.0.11: icmp_seq=2 ttl=128 time=0.254 ms
^C
--- 172.20.0.11 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 4ms
rtt min/avg/max/mdev = 0.254/0.256/0.259/0.016 ms

看起来 Linux 和 Windows 已经互通了,但是去路由器里面测试一下。

root@OpenWrt:~# ping 172.20.0.8
PING 172.20.0.8 (172.20.0.8): 56 data bytes
^C
--- 172.20.0.8 ping statistics ---
7 packets transmitted, 0 packets received, 100% packet loss

看起来情况不妙,路由器似乎不认识它们。

root@OpenWrt:~# ping 172.20.0.8 -I br-lan
PING 172.20.0.8 (172.20.0.8): 56 data bytes
64 bytes from 172.20.0.8: seq=0 ttl=64 time=0.311 ms
64 bytes from 172.20.0.8: seq=1 ttl=64 time=0.276 ms
64 bytes from 172.20.0.8: seq=2 ttl=64 time=0.237 ms
64 bytes from 172.20.0.8: seq=3 ttl=64 time=0.258 ms
^C
--- 172.20.0.8 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.237/0.270/0.311 ms

这次我们指定 ping 使用接口 br-lan 后成功了,看来路由器需要手动配置 172.20.0.0/24 网段的路由才行。

route add -net 172.29.0.0/24 dev br-lan

查看配置后的路由表

root@OpenWrt:~# route -en
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
172.20.0.0      0.0.0.0         255.255.255.0   U         0 0          0 br-lan

再次尝试

root@OpenWrt:~# ping 172.20.0.8
PING 172.20.0.8 (172.20.0.8): 56 data bytes
64 bytes from 172.20.0.8: seq=0 ttl=64 time=0.288 ms
64 bytes from 172.20.0.8: seq=1 ttl=64 time=0.444 ms
^C
--- 172.20.0.8 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.288/0.366/0.444 ms

自此 172.20.0.0/24 私有网段配置完成,接下来需要配置 ZeroTier 的路由。

🎉 配置 ZeroTier 路由表

image.png
这里 via 指定由哪一个节点进行转发,自然要填入路由器分配到的地址了。

稍安勿躁,看测试结果

image.png
到了这里基本上完成后需求的后半部分:路由器下的设备分配独立的 IP 地址,且能被 ZeroTier 其它节点访问。

最后一步

添加静态路由表
image.png
之后路由器重启后也可以恢复之前的配置。

🐶 可选 - 为 ZeroTier 创建接口和防火墙

这一步其实可有可无,不过创建完成接口后就可以在“接口”里面看到“ZeroTier”流量使用情况了。

  • 创建接口

image.png

  • 创建防火墙区域

image.png
开启“zerotier”的转发后,理论上不需要手动添加 iptables 表了,但是我测试的时候没有成功,因此依旧保留 iptables 的添加。

📆 总结

总算是解决了网络问题,应该可以安心写代码了。