Vagrant share浅析

时间:2022-05-06
本文章向大家介绍Vagrant share浅析,主要内容包括这是怎么做到的?、我猜我猜...、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

好吧,今天的文章只和程序有关,和人生无关。连续喝了几天大馇子粥,该上点清香逸人的咖啡了。

如果你不知道啥是虚拟机(vagrant是一款虚拟机管理软件),看到这里可以休息休息眼睛,明天的连载传记『途客们的旅行梦』再见。

TL;DR

最近vagrant 1.5升级力度空前,增加了很多新功能,其中最令人瞩目的当属 vagrant share。啥子意思呢?就是把你的虚拟机share给地球另一端的人。这功能很高大上啊,简直是居家旅行,远程办公的必备武器。你正在做的web app出bug了,需要帮忙?没问题,亲,把虚拟机share一下。

➜  dockerbox  vagrant share
==> default: Detecting network information for machine...
    ...
==> default: URL: http://cheerful-beaver-2087.vagrantshare.com
...

我的虚机里开放了3000端口,是个web app。share好以后,别人就可以使用这个链接:http://cheerful-beaver-2087.vagrantshare.com,访问程序君正在调试开发的app了。(别试了,当您看到本文时,程序君已经把共享关闭喽)。

很神奇吧?(更有意思的vagrant connect有待你自己去发掘)

这是怎么做到的?

估计你有和程序君一样的问题。程序君开始捣鼓。

首先tcp dump抓包。

➜  appshare git:(master) ✗ tcpdump -i en0

内容很多,就不在这里呈现了。没有太多实质的内容,主要是下面几个步骤:

(1) DNS请求 vagrantcloud.com 获得两个IP: 107.23.21.165, 54.85.101.30

(2) 分别进行https握手(详细内容见知乎)

(3) 传输数据 blablabla(这不废话么)

郁闷的是vagrant考虑到数据安全性,全部采用https,所以无法窥探里面的究竟。

为什么不用Fiddler来偷窥?好吧,fillder基于.net,程序君不想在mac上装mono...

所以程序君只能靠脑子生猜这个功能是怎么实现的了。

我猜我猜...

可能的实现手段:

(1) 使用ssl V**。具体做法:

local http server --- sslV** client ===== SA --- cloud http server

当ssl V** tunnel建立成功后,localp http server和cloud http server间就跟局域网一样可以直接访问。从浏览器访问过来的数据,可以被proxy到local http server,而不用担心网络连接。

不过,vagrant share不是这么实现的。因为建立ssl V**后ifconfig会看到新的tunnel interface。而vagrant share之后,没有新的interface。

(2) 使用tcp proxy。具体做法:

local http server --- local proxy --- cloud proxy ---- cloud http server

用户从url访问过来的http请求,被cloud http server负载到cloud proxy,然后cloud proxy再将其relay给local proxy,local proxy再relay给local http server;http响应反之。

这个想法比较靠谱。

试着用go简单实现了一下,主要是为了验证想法。结果证实了这个方案可行(我搭了个本机的环境):

local http server (8000) --- local proxy  --- (8211) cloud proxy (8211) ---- cloud http server

由于我在测试,所以不需要放一个nginx在cloud http server侧,直接访问:http://192.241.1xx.xx:8211(我的一台ditalocean服务器)即可。经过两层proxy,local http server的内容被转到浏览器上。当然,目前的代码有问题,local proxy和cloud proxy间只有一个tcp connection,遇到keep-alive的http connection就阻塞住了...然后,然后后续的connection的数据就过不去了(堵车),所以你看到的页面是这样(local http server跑的是我的博客):

哈,给你一个到处都能访问的url,你就可以访问我本机的某个web app了。

方案没有大问题,需要注意的是下面几点:

(1) cloud proxy监听一个端口(如8211),等待http server或者browser过来的http request。

(2) cloud proxy监听另一个端口(如8210),等待local proxy的连接。注意因为local proxy(跑在用户的机器上)没有确定的公网地址,所以cloud proxy只能被动等待连接。

(3) local proxy启动后就要和cloud proxy建立持续的tcp connection。当cloud proxy有数据到达时(http request),cloud proxy才建立和local http server的tcp连接,将http request转至local http server。

(4) 基于以上前提,cloud proxy要先运行起来,然后是local proxy。

另外,如果真要把这个东西做成像vagrant share一样(先不考虑https),则需要:

(1) 自动生成唯一且难以猜测的名字。如 easy-sheep-9048.share.tchen.me。并且client proxy和cloud proxy能根据它找到二者之间的连接。

(2) 域名提供商能够支持泛域名解析(最好三级域名也支持),dnspod免费版支持二级。

(3) nginx server配置将泛域名作为http request的一个参数传递给cloud proxy,然后cloud proxy可以区分对应的是哪个share。

有空程序君再把它捣鼓好吧。