在文章的开头我想向大家介绍一下我们团队:kungze。kungze 音译“昆泽”, 意为昆仑山上的白泽。我们由是一 群从事云计算的伙伴组建的兴趣小组,我们的目的是把我们在工作中的一些脑洞以代码的形式实现,并通过 github 向大家开 放,期望得到更广大,更专业的同行的建议与反馈,完善我们的项目与脑洞。我们在 github 的仓库地址:https://github.com/kungze,欢迎 大家登录参观,如果您觉得其中某个项目对您有用,或者是一个具有潜力的项目,请给这个项目来个点赞收藏吧,您的点赞就 是我们的动力,我们也会优先发展点赞最多的项目。
接下来进入正题,为大家介绍我们 quic-tun 项目,代码仓库:https://github.com/kungze/quic-tun。 正如标题说描述的,我们开发这个项目是用来优化在不稳定网络环境下的流量传输的,尤其是在有丢包环境的网络, 比如远距离传输的公网环境。其核心原理:把本地 TCP 流量转为 QUIC, 使用 QUIC 协议在公网环境传输,流量到达目的端后在转为 TCP。可以理解为使用 QUIC 协议为 TCP 应用搭建了一个传输隧道。
下面是我们在不同丢包环境下使用原生 TCP 传输和使用 quic-tun 传输两种方式带宽的对比,测试工具使用的是 iperf3。
- 原生TCP
丢包率 (%) | 发送(Mbits/sec) | 接收(Mbits/sec) |
---|---|---|
0 | 562 | 561 |
0.1 | 307 | 306 |
0.5 | 80.2 | 79.9 |
1 | 60.7 | 60.3 |
5 | 13.0 | 12.8 |
- quic-tun
丢包率 (%) | 发送(Mbits/sec) | 接收(Mbits/sec) |
---|---|---|
0 | 604 | 601 |
0.1 | 348 | 344 |
0.5 | 239 | 235 |
1 | 138 | 135 |
5 | 38.8 | 36.4 |
可以看到即使在没有丢包的环境,quic-tun 对带宽也有些许的优化,随着丢包率的提高 quic-tun 的优势也越来越明显。
quic-tun 优化传输的核心就是使用了 QUIC 协议,其是谷歌制定的一种基于 UDP 的低时延的网络传输层协议,有着优秀的丢包重传 算法和拥塞控制算法,目前 HTTP3 就是基于 QUIC 协议的。quic-tun 不仅借助 QUIC 优化了基于 TCP 协议的应用的流量 的传输,还提供了一些其他功能来使应用在公网传输更便捷更安全。
端口聚合
这里指的和交换机的端口聚合并没有关系,这是我们自定义的一个概念(我实在想不到一个别的词来概括这个功能),大家不要混淆概念。 简单描述,这个功能解决的问题就是:当我们在服务端有多个应用服务(即使是不同的应用),我们也仅需要在公网暴露一个 UDP 端口, 所有应用通过这个 UDP 端口传输。示意图如下:
为了实现这个功能我们引入了 ”token“ 的概念,在隧道建立阶段,客户端(quictun-client endpoint)程序通过插件获取 token, 传送给服务端(quictun-server endpoint),服务端解析 token 获取客户端想访问的应用程序的地址。
客户端通过两个命令行参数: --token-source-plugin
和 --token-source
来决定获取 token 的方式,我们支持多个 token-source-plugin
, 其中 Fixed
是 quictun-client 默认的 plugin,也是我们最简单的一个 plugin,这种 plugin 每个客户端的 token 是固定的,也就是说通过这个客户端,客户端一侧的程序只能访问固定的服务端应用程序,需要访问多个服 务端应用程序就需要启动多个 quictun-client,下面是该 plugin 的一个使用示例:
./quictun-client --listen-on tcp:127.0.0.1:6500 --server-endpoint 172.18.31.36:7500 --token-source tcp:172.18.30.117:22
上面命令行中的 tcp:172.18.30.117:22
就是一个 token,由于 --token-source-plugin
的默认值就是 Fixed
, 所以 --token-source-plugin
可以不用指定。
在服务端 quictun-server 通过 --token-parser-plugin
和 --token-parser-key
确定如何解析 token,由于上面 客户端程序 quictun-client 使用的是明文指定的 token(字符串:”tcp:172.18.30.117:22“ 没有经过任何加密)。这 与 --token-parser-plugin
和 --token-parser-key
默认值相符所以在启动服务端程序时可以不指定这两个参数。
./quictun-server --listen-on 172.18.31.36:7500
注意:这里为了行文方便把启动客户端程序的命令行放在了前面,正常的顺序是要先启动服务端程序在启动客户端程序。
关于 token 的更多信息可以参考quic-tun 项目文档。
- SSL 加密与认证
在公网传输最重要的就是数据安全,SSL 是当前数据加密的标准解决方案,由于 QUIC 是强制要求 SSL 证书的,通过 QUIC 建 立起来的通道原生支持了加密,所以这一块没什么可以讲的了。接下来我们重点看一下认证,认证分为两种情况:客户端认证服务端, 服务端认证客户端。quictun-client 和 quictun-server 都是通过 --verify-remote-endpoint
和 --ca-file
来开启对 对方的认证的。--verify-remote-endpoint
默认值为 False,设置为 True 则会认证对端,--ca-file
指定的是给对端公钥签 名的 ca 的证书。更多关于 SSL 参数相关的介绍请参考quic-tun 项目文档。
介绍完功能,我们来看一个 QuickStart 示例
从 release 页面下载最新版本的 quic-tun 压缩包,注意选择合适平台,然后解压:
wget https://github.com/kungze/quic-tun/releases/download/v0.0.4/quic-tun_0.0.4_linux_amd64.tar.gz
tar xvfz quic-tun_0.0.4_linux_amd64.tar.gz
启动服务端程序:
./quictun-server --listen-on 172.18.31.36:7500
监听的地址根据实际情况调整,启动后 quictun-server 将会监听在一个 UDP 端口。
启动客户端程序:
./quictun-client --listen-on tcp:127.0.0.1:6500 --server-endpoint 172.18.31.36:7500 --token-source tcp:172.18.30.117:22
客户端 --listen-on
监听的是一个 TCP 端口或者一个套接字文件,--server-endpoint
要和 quictun-server 的 --listen-on
保持一致,--token-source
用来指定通过这个客户端程序(127.0.0.1:6500)能访问的服务端应用程序的 地址(是一个 TCP 或 unix 套接字),这个示例我们服务端应用程序是一个 SSH 服务。
使用 ssh 命令测试:
$ ssh root@127.0.0.1 -p 6500
root@127.0.0.1's password:
最后来介绍一下 quic-tun 计划支持的功能和可能的应用场景,如果您有一些好的点子,请在评论区留言告诉我们:
功能:
- 添加 API 接口,查看当前已经建立的隧道,并展示隧道流量
- 支持 UDP 打洞,是位于不同局域网的两个程序也能互相访问
应用场景:
- 云桌面领域
云桌面常用的协议:RDP,SPICE,VNC 等都是每个虚机需要监听自己的端口,如果想让云桌面通过互联网被远程使用那么 我们需要为每个虚机在公网暴露一个端口,这无疑增加了安全风险与应用的复杂度。通过 quic-tun 仅需要在公网暴露一个 UDP 端口,通过这个端口代理访问各个虚机。
- 边缘计算领域
边缘计算中边缘设备所处网络环境是不确定了,有可能是一个很恶劣的环境,通过 quic-tun 能极大的改善网络传输状况。