我有一台台式机,配置比较高,放在家里,有一台笔记本随身带着。由于个人工作和兴趣原因,我经常在台式机上使用虚拟机创建不同的开发环境。如果是在同一个局域网中,一般不存在这个问题,使用“桥接模式”和主机共享一个 IP 地址段,我就可以在笔记本上通过 IP 直接访问这些虚拟机上的服务。
如果出门了呢?这个时候就不能通过 IP 直接连接了,需要借助于内网传统的工具。之前我一直都用的是花生壳和 ngrok,花生壳有 2 个免费映射的额度,ngrok 只有 1 个,相当不够用,我记得有一段时间我同时做三个不同事情的开发,使用三套不同的开发环境,那个时候人还在外地,导致我要频繁删除、创建花生壳和 ngrok 的映射。
有没有一个可以不用“额外付费”的内网穿透工具呢?因为我后面要提到的开源工具,需要用到一个公网的服务器作为转发。当然我手上有一个云服务器,对我来说就不算“额外付费”,但是对于没有开通云服务器的朋友来说,可能还是需要对比一下方案成本的,这里就不再详述。
ztm
ztm(https://github.com/flomesh-io/ztm)是一个基于 pipy(https://github.com/flomesh-io/pipy)构建的网络基础设施:
ZTM is an open source network infrastructure software for running a decentralized network. It is built upon HTTP/2 tunnels and can run on any sort of IP networks such as LANs, containerized networks and the Internet, etc.
根据 Github 仓库上的 README 示例:
Data Center
+-------------------------------------------+
| Hub |
| (state in ~/.ztm/ztm-hub.db) |
+-------------------------------------------+
HTTPS | Port 8888 HTTPS | Port 8888
| |
------------|---------------------------------|--------------
| Firewall |
------------|---------------------------------|--------------
| |
| Internet |
| |
---------------------------- | ----------------------------
Firewall | Firewall
---------------------------- | ----------------------------
| | |
| | |
+--------------------------+ | +--------------------------+
| Agent @ Home | | | Agent @ Workplace |
| (state in ~/.ztm/ztm.db) | | | (state in ~/.ztm/ztm.db) |
+--------------------------+ | +--------------------------+
|
我设计的实验方案是创建两台虚拟机,一台装 Windows 10,一台装 Ubuntu 22.04,这两台电脑不属于一个网段,不能直接访问。首先我们准备实验环境,大家可以根据自己的需求进行修改:
- 云服务器:Ubuntu 22.04,作为 ztm hub,用来转发流量;
- 笔记本:要求能访问互联网,ztm agent 节点,作为 ztm mesh 的 root 用户,用来对其他 ztm agent 签发证书;
- Ubuntu 虚拟机(IP:192.168.2.137):Ubuntu 22.04,ztm agent 节点,用来部署测试服务;
- Windows 虚拟机(IP:192.168.2.138):Windows 10,ztm agent 节点,用来访问测试服务。
这里说明一下,我在配置虚拟机网络设置的时候,都用的 NAT 模式,没配出来互相独立的网段,导致这两台电脑还是属于一个网段,所以我直接在 Ubuntu 虚拟机上使用以下命令,对 Windows 虚拟机的 IP 进行了限制访问:
sudo iptables -A INPUT -s 192.168.2.138 -j DROP
这样 Windows 虚拟机就无法直接访问 Ubuntu 虚拟机了,可以使用 ping 192.168.2.137 在命令前后测试一下,可以使用 sudo iptables -D INPUT -s 192.168.2.138 -j DROP 进行恢复。
我们首先在 ztm 的 Github 页面上下载安装包,注意需要从 Actions 页面上下载,这里才是最新版,不要从 Releases 页面下载,下载 windows-build:

云服务器
在 Ubuntu 22.04 我们采用源码编译,因为上面的 linux-build 在 Ubuntu 22.04 上运行会碰到一个 GLIBC 版本问题,其他编译环境请参考Build 文档:
apt update
apt install clang cmake npm
git clone https://github.com/flomesh-io/ztm.git
cd ztm
./build.sh
我们把编译好的 ztm 二进制文件放到 PATH 路径下,运行以下命令启动 ztm hub:
sudo /home/admin/bin/ztm start hub --listen 0.0.0.0:8888 --names {IP 或者 Domain}:8888 --permit root.json
这里注意它会在当前运行命令的目录下生成一个 root.json 文件,使用该文件加入到这个 Mesh(网格) 的节点拥有这个 Mesh 的 root 权限,也就是可以邀请用户。
笔记本
我这里使用的是 Mac,我也是使用源码编译方式得到 ztm 命令行,我们把上一步从云服务器启动 ztm hub 生成的 root.json 文件拷贝到本地,首先需要启动 ztm agent:
ztm start agent
我们打开浏览器,访问 http://localhost:7777,agent 服务默认监听在 7777 端口。我们点击欢迎界面的 Join Mesh 按钮填写信息,网格字段填写方便你识别的网格名称,端点字段填写方便你识别的端点名称,选择上一步的 root.json 作为右侧的许可证,点击保存:


点击端点页面的右上角,进行到证书签发,后续需要将两台虚拟机(Windows 和 Ubuntu)生成的 identity 发送给 root 用户进行签发,下载签发后的文件发送到对应的 agent 节点:

Windows 虚拟机
在 Windows 上直接使用 ztm 提供的安装包(前面提到的 windows-build),推荐把安装 ztm 的目录加入到 PATH 环境变量中:

启动 ztm,点击右上角下载 identity 文件,发送给 root 用户进行上一步的签发,得到 permit 文件:

在进行证书签发的时候,需要配置用户名,这个是一个逻辑的用户,一个用户可以拥有多个端点,这个端点可以理解为进程,因为一台物理机或虚拟机上可以运行多个端点,跑不同的 Mesh,这个在后续文章中会深入解释这些概念。

Ubuntu 虚拟机
Ubuntu 虚拟机的操作也与 Windows 虚拟机类似,启动 ztm agent,下载 identity,发给 root 用户签名,拿到签名后的 permit 文件,使用该文件加入 Mesh。
经过一番操作之后,回到我的笔记本上,这个时候我们能看到的端点应该如下:

然后我们在 Ubuntu 虚拟机启动一个监听在 127.0.0.1:5000 的服务,注意此时 Windows 虚拟机是无法直接访问 Ubuntu 虚拟机的。
内网穿透
在 Windows 虚拟机上通过应用页面的隧道进行配置:

入口选择 leo-vm-windows,监听 127.0.0.1:5001,出口选择 leo-vm-ubuntu,目标 127.0.0.1:5000。

访问成功!
