之前放了几台洋垃圾做服务器放点 API 之类的东西,走了桥接的网络然后用 DDNS 的方案做服务发现。但有个最大的缺点就是 DDNS 自有的 DNS TTL 导致网络重拨时的服务不可用明显,所以需要撸一些替代方案了

目前可以考虑的只有以下几个方案(代价较高的方案不考虑)

方案详细做法优点缺点
DDNS公网 IP + DDNS访问服务时直连(减少链路)DNS TTL 延迟影响、要求有公网 IP、端口屏蔽限制
IP 上报IP 上报到 Gateway 机器(大部分在海外)做 4 层 Proxy秒级更新要求有公网 IP、端口映射维护成本
代理组网通过组网把 Gateway 机器打通再做 Proxy秒级更新端口映射
代理组网 + NAT组网后用 NAT 做独立 IP 栈接近原生公网网络栈复杂

加上最近计划把几台机器集合起来用 KVM/QEMU 做点小鸡出来把玩所以选择了「组网 + NAT」的方案,最大的好处就是可以让小鸡可以直接分配公网 IP(NAT)用省去了处理端口映射的烦恼。

代理选型

比较早的时候尝试过用 OpenV_N 把家里网络跟腾讯云打通,但总体配置较为麻烦且如果要再做一些网络的管理感觉投入比较大。所以这次我们选择了 Zerotier 作为组网工具。这个工具其实我关注了比较久了,而且也预先尝试过几个场景组网,感觉靠谱。

It's a distributed network hypervisor built atop a cryptographically secure global peer to peer network. It provides advanced network virtualization and management capabilities on par with an enterprise SDN switch, but across both local and wide area networks and connecting almost any kind of app or device.

以上是来自官网的介绍,简单可归结为以下几点

以上的点足以让我满意,就不再说其他的优点了,可能在后续的文章会介绍和使用其他的特性。

开搞

Zerotier 组网

本文不是 Zerotier 的使用说明所以不会详细的说到各个点

Zerotier 官网 注册账号并创建网络(注:这货有免费版也有收费版)。

F256E3EC-7242-44B2-B278-839E595F7026.png

每个网络会分配一个 Unique ID,这个 ID 在后续用在加入或者管理等各个地方。进入网络详情后选一个段做 Zerotier 的内网段(注意不要现有的网段冲突)家里的网段是 10.2.2.0/24 所以随意的选一个 192.168.193.0/24

0C6C3C62-49AF-4E1A-9171-CCF9088B9A42.png

curl -s https://install.zerotier.com/ | bash 快速的安装 zerotier-clizerotier-one (后者是 daemon 进程),然后用 zerotier-cli join <networkID> 把所在节点加入网络即可

Moon

在 Zerotier 里有所谓的 Earth 和 Moon 节点,分别是官方的根服务器和自己搭建的子服务器。他们作用相同,主要用来做 Peer 寻址,在大中华局域网内非常建议做一个 Moon 节点来加速整体网络。此外如果机器在 NAT 后无法直连的还会通过 Moon 做网络转发。本篇不赘述搭建 Moon 的过程和使用。

实际组网

我的想法是家里的网络无需各个节点都分配 Zerotier 的 IP,只需要在网关上做 Gateway 把两个网络打通即可。结果发现用的路由器(Ubnt ER-X) 的架构是 MIPS 而官网恰好不支持。所以只能曲线救国多一个 hop 了。在路由器上做 static route next-hop 把所有 ZT 的网段转到内网的一台机器(简称为 HPG)上。然后把 HPG 加入到大内网即可。

假设 HPG 分配到的 IP 是 192.168.193.2 在这台机器上需要做下 MASQUERADE 如下

用 zerotier-cli listnetworks 或者 ip a 看下 zerotier 给到的 interface 叫啥,比如说

# ip a
...
7: ztqu3drtux: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 2800 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/ether a6:68:42:2b:41:ae brd ff:ff:ff:ff:ff:ff
    inet 192.168.193.2/24 brd 10.1.2.255 scope global ztqu3drtux
       valid_lft forever preferred_lft forever
    inet6 fd83:48a:632:b2c8:a599:93a0:f019:4724/88 scope global
       valid_lft forever preferred_lft forever
    inet6 fcb1:b642:a3a0:f019:4724::1/40 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::a468:42ff:fe2b:41ae/64 scope link
       valid_lft forever preferred_lft forever

看到是 ztqu3drtux,然后给这货加个 MASQUERADE

iptables -t nat -I POSTROUTING -o ztqu3drtux -j MASQUERADE

然后记得把 IP Forward 开了

echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
sysctl -p

然后还需要在 Zerotier 网络中配置下发的家里内网路由

C161F121-03C2-4ABD-B098-C57FA53440A4.png

然后组网就完成了,家里的网段跟 Zerotier 该 Network 上的所有节点都已经连通。

但实际上 Zerotier 还有很多可以做的东西,比如说接入他家的 API 做一些监控以及还提供了更复杂的网络策略。以后用到再写出来吧。

打通外网

接下来就是找条好线路搞一些 IP 拿来做 NAT 了,目前只是搞了几个 IP,差不多一个 ¥15,

老操作把 NAT 机器开了 IP Forward 然后加入 Zerotier 的内网

echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
sysctl -p

zerocli-cli join xxx

这时候就打通了整个网络了,接着就是做 NAT。自己在 /etc/network/interface 把租的几个 IP 都给加到不同的 interface 上。然后两句话搞定

PUBLIC_IP=$1
PRIVATE_IP=$2
GATEWAY_IP=192.168.193.222  # 这个是 Gateway 的 Zerotier IP
iptables -t nat -A PREROUTING -d ${PUBLIC_IP} -j DNAT --to-destination ${PRIVATE_IP}
iptables -t nat -A POSTROUTING -d ${PRIVATE_IP} -j SNAT --to-source ${GATEWAY_IP}

总结

这一波操作下来,最难受的就是路由不能用 zerotier 导致跨网的时候都会多一跳。现在所有内网的机器都可以拥有独立的公网 IP。按目前的规划家里的机器大概可以弄 50 台小鸡出来,其实如果自己去租个 C 段会更便宜(大概一个 C 是 ¥500)反正自己也有 ASN 不过目前用不到那么多,先临时搞着。

但其实目前方案还不靠谱也不够漂亮,可能不久后以 route 的形式再出一个方案吧。如果有多个物理隔离的网络,到时候各自域内的网关上做成 zerotier node 就可以全通了。