BadVPN详解之--组网原理剖析

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                这可能是第一篇关于BadVPN原理的中文介绍,所以我恪守职责,希望能将BadVPN的原理阐述清楚,而不仅仅是为了欺世盗名取天下之先。

序:格尔上市

这一段插在这里有点突兀,与BadVPN无关,只是我的一点实感,忽略即可。
       明天小小要去厦门演出,今天是什么日子?是小小准备且出发的日子。但是同样在今天,也就是2017年4月21日(写完本文时估计已经到了22日...),上海格尔软件股份有限公司成功上市了。也许你不知道这个公司,确实这公司的业务是很小众,不像BAT布局那般宏大,但这并不意味着这家公司的平庸。于公于私我不得不多说几句。

于公的宣传

格尔软件是专门搞PKI的一家公司,也许你不知道什么是PKI,但没关系,只要百度一下就好,概念很简单,不需要Google。格尔是国内少数几个搞PKI的公司之一,而且也算是龙头之一吧。做个比喻,如果说腾讯依托其QQ,微信成为了社交APP的龙头,那么格尔就是国内PKI产业的龙头(我有点带有感情色彩,不管是对腾讯还是对格尔,我只是想说公司好),那么PKI产业包括什么?它包括身份认证,访问控制等,而这些在互联网时代是每个人的基本需求。
       在互联网时代,信息安全已经不仅仅是组织,机构,国家的事情,而是关系我们每一个人,这是一个非常有前途的产业,虽然仅凭信息安全无法成就像Google,fb,腾讯,阿里那般的格局,但是这并不意味着那些诸如BAT之类的巨头可以忽视信息安全,相反,他们需要更加重视信息安全,要么自己做,要么购买既有的解决方案或与其深度合作,让专业的人做专业的事。诚然,格尔做不出像微信这样的APP,也无法成就像支付宝那帮风风火火的互联网支付的宏大场面,但这些一开始就并不是格尔的目标,格尔的目标是为所有这些提供底层的安全保障。
       格尔公司成功的与包括华为,腾讯在内的第一梯队巨头企业达成了合作和交流,与其一起深度合作,为构建安全的基础设施提供保障,卸载了这些巨头企业的巨额开销,这些事情做的很棒!
       如今格尔成功上市,我心里表示高兴,于我个人而言,我供职过的公司成功上市,我当然觉得风光,毕竟,我也是为其奋斗过的人,哪怕,只是为了自己,即使,现在在利益方面已然与我无关。

于私的感恩

在N多家公司为自己奋斗,为了自己能在一个大城市买上房子,成家立业,这几乎是每个IT人的梦想,当然,我也在此之列。虽然我早已离开了,但我感谢格尔公司,是它让我在上海立足了根本,买了自己的第一套房子,在公司期间,我和老婆生育了可爱的小小并伴随其快乐成长。
       也许,很多人会觉得我傻,不就是一家公司吗?到哪不是工作,你工作,老板给钱,天经地义。但是这对我不一样!
       像很多华中科技大学(原谅我总拿这学校开涮,其实我是做过统计的)的毕业生,毕业就能到腾讯,到华为这种大厂,这当然是很好的事,我并不嫉妒,我的父亲告诉我要为别人的幸运感到庆幸,因为幸运的人越多,自己的机会就越多,毕业进大厂这使得他们无需多个城市,多家公司折腾,可能一生就在三地生活过就够了,自己的老家,武汉,以及深圳。对于这种高材生,我祝福他们,对于另一类高材生,那些毕业于北京,上海一等名校(我故意把北京上海的名校和武汉的这种技校相区别,请别介意,其实都一样,together with哈工大,哈工程,北航,南航...)然后出国再回来的海归,我更应该祝福他们,以上这两类人才无论如何在任何时候都可以待价而沽。慢慢的,圈子就已经完全被他们所占据,至少华为对学校是有要求的吧。这导致像我们这种不入流的两年制大专生很难找到像样的工作,那些名校的科班生,那些校招进大厂的他们根本无法体会我们这种辛苦找工作的求职者心里的酸楚。他们跟我们完全处在两个世界。
       对于那些势利眼的面试官或者HR而言,他们一听到我的资历就会马上在心里做一个MARK标记,与LRU相反,是最近最常用的标记,如果要PASS掉某些人,他们会优选我这种。然而,世事总是有例外,就这样在我2009年裸辞后三个月求职未果,不经意间老婆帮我投了个简历,在2010年3月29日去格尔面试的时候,一头长发的小雨跟我面谈了不到半小时就让HR给我打电话,我还没到家就接到了入职邀请,小公司,没有Offer,没有什么正式的文件,只说能不能下周一上班(事实上,我是在3月24号周三才去上班,前两天好好吃了几顿,睡了几觉,因为找到工作对我而言太重要,我必须把这件事当成一件喜事而庆祝。这是批量的名校科班毕业生所完全不能理解的)...
       于是我一干就是五年,其中第一年我恍恍惚惚,再往后就看我的博客吧。我很感谢格尔能给我这个学习成长的机会,为我提供各种机会和资源,让我精通了VPN,精通了网络,最终让我彻底抹掉了学校和学历的阴影,并且在将近10年以后成功入职了大厂,我觉得这是格尔带给我的,作为回馈,我只能继续努力,好好供职于我现在的公司,毕竟鹅厂也同样没有因为我的学校和学历而计较,我突然感到我是幸运的人。
       来之不易才懂的珍惜,人要记着对自己好的人或者事,不仅仅是因为利益,总把任何东西看成利益,那太Low。总之,无条件谢谢我的父母,我的家人,格尔公司,鹅厂,...!
       感慨发完,可以步入正题了。

前言

我关注VPN已经多年了,有三类VPN让我觉得惊叹帮我理解了网络协议的体系结构。首先IPSec,I2TP,PPTP这种传统的VPN技术让我知道原来协议栈还可以如此的相互Over,然后就接触到了OpenVPN,如此一个简单的玩意儿竟然拥有如此强大的组网能力,我喜欢这个OpenVPN,一去就是三五年,期间这个玩意儿也为我带来很多现实的东西,比如奖金,比如加薪升职什么的,打心眼里,我觉得利用OpenVPN的理念,可以创造出世界第一等的VPN产品...直到我遇到了BadVPN!
       当然,最基本的VPN就是IPSec VPN,然而要想配置好一个多点的IPSec VPN网络及其复杂和费事,最终EzVPN弥补了这个不足,它通过一个所谓的中心节点简化了配置。然而这一切都是“官方”的方案。落实到普通程序员可以就地使用的方案,没几个。OenVPN是一个,BadVPN也是一个。
       我承认,前几年我被OpenVPN冲昏了头脑,竟然忽略了世界上还有一个叫做BadVPN的东西。都到了2017年了,我才第一次注意到它,这多多少少有点让自己觉得悲哀。

BadVPN是另一个VPN

为了能快速理解BadVPN的原理,我准备从OpenVPN开始,当你知道了OpenVPN有什么问题的时候,就会更加容易理解BadVPN是如何解决这些问题的了,而这些正是理解BadVPN的关键。我先来展示一个OpenVPN的结构图,假设使用TAP Bridge模式:




可以看出,OpenVPN有一个所谓的“中心节点”,其它所有的子节点都连接到这个中心节点。OpenVPN的这个中心节点身兼两职:
1.提供总体的控制功能,负责与子节点密钥协商,分配虚拟子网的IP地址给子节点,推送策略给子节点等。
2.同时作为一个对等的VPN节点存在,和各个子节点所携带的子网互联互通。

上述两点可以看出,第一点是控制平面的功能,第二点是数据平面的功能,二者完全在一个链路上传输,这意味着什么?这意味着要精心设计OpenVPN的协议,以区分到来的数据包包含的是控制信息还是数据。
       OpenVPN协议区分了数据是控制面的数据还是数据面的数据,然而这种区分是带内实现的,也就是说通过协议头的字段来实现的,姑且不说封装这个协议头会带来什么开销,仅仅在OpenVPN进程中去多路复用并行处理控制平面和数据平面就够复杂的了。
       按照传统的网络设计观点,中心节点即服务端就是一个交换机,而各个VPN子节点客户端就像是“该交换机端口的另一端”连接的各个主机或者级联交换机,这是一个典型的星型拓扑。然而按照SDN控制平面的观点来看的话,中心节点就是一个控制器,它控制了整个的VPN网络转发逻辑,所有的子节点要发送数据必须无条件转发到中心节点,让中心节点决定数据转发到何方,这意味着哪怕是子节点客户端之间互相通信,也必须经由中心节点来转发。
       不管站在什么立场上来看,OpenVPN的中心节点都是一个单点,不管是从效率还是从可用性上来权衡,这都不是一个优雅的方式。说点题外话,幸亏我个人精通Linux网络,可以通过iptables,iproute2,多线程改造OpenVPN,bonding TAP网卡,Keepalived等措施来破除这种限制,消除种种效率和可用性上的威胁,我才得以驾驭OpenVPN,不然的话,用OpenVPN来组网还真的限制多多。即便我有能力Hold住存在单点问题的OpenVPN,最终我还是失败了。我已经把OpenVPN堆积的不成样子了,迫切需要一个新的思路。

       OpenVPN的中心节点扮演了过于重量级的角色,这导致了任意建立VPN通道的节点之间的关系不可能是对等的,OpenVPN必须以主从方式建立VPN通道。这就主从结构的限制使得OpenVPN在组网方面很难构建多点对多点的网状拓扑。

    那么BadVPN有何不同呢?为了与OpenVPN做对比,我还是先来展示一个BadVPN的总览图:




所有的节点综合起来构成了一个巨大的交换机,大家一起完成交换机的功能,各个VPN子节点(为了对比,我依然沿用OpenVPN中心节点,子节点的术语)就是交换机端口本身,而不再是“端口对端”连接的设备。其中,中心节点不再负责实际的数据转发,而仅仅作为一个“维护这个交换机组成部分”的控制器存在,中心节点负责以下的事宜:
1.记录该VPN网络中拥有多少节点主机,即“该大交换机中有多少端口”以及“端口的添加,删除以及通告”。
2.构建子节点与中心节点之间,子节点与子节点之间的TLS控制通道,协商子节点之间的通信密钥。

这意味着各个子节点之间的VPN互通不再需要经过中心节点,实际上也根本就没有什么可以进行数据通信的VPN中心节点。VPN通信节点之间变成了真正的点对点通信,除非你配置中继(BadVPN的一种特殊运行方式,在权限受制的场景下使用,本文不讨论,详情参见BadVPN的Document),任何VPN之间的通信都是直接通信,不需要经过第三方。
       这意味着什么?
       这意味着:
1.BadVPN的协议会非常简单。
2.BadVPN的处理过程会非常简单。

BadVPN将控制平面和数据平面做了带外的分离,不再仅仅是带内分离而依靠协议来区分。关于这一点,后面会详述,下面的小节我们在感官上认识一下BadVPN的原理。

BadVPN的运行原理图解

长篇大论终究会因为文笔不好而适得其反,所以还是通过画图具体来点情景分析为好。我分两种场景来描述BadVPN的行为,即非打洞场景和打洞场景,先看非打洞场景。

1.普通情形的情景原理分析

控制面的生成

第一个节点连接中心节点时




第二个节点连接中心节点时




第三个节点连接中心节点时





三个节点都连接上了中心节点,本文中描述的“BadVPN构成的巨大交换机”就已经生成了,我们可以看到,是中心节点维护了这个巨大的交换机。
       这个时候,这个交换机是空的,就像刚上好架,插好网线,加电完毕后的状态一样。我们知道,以太网交换机是自学习的,本文中叙述的“BadVPN交换机”自然也不例外。那么下面我们就看一下在有实际数据传输的时候,这个交换机到底是怎么运作的吧。


数据面的运作

子节点A或其携带子网需要ping子节点B的TAP地址,发送ARP




子节点A收到子节点B的TAP回复的ARP Reply




子节点A封装ICMP Ping在加密通道上发给子节点B




附:我的改进

其实我不很赞同BadVPN里面的Peer-Macs表的设计,我觉得应该是三元组设计,即Peer-Vips-Macs表,详见我下一篇文章,讲述我自研的一个VPN,可能介于OpenVPN和BadVPN之间,也可能是BadVPN介于OpenVPN和我的VPN之间...谁知道呢?总之,皮鞋爆炸。

2.NAT后需要打洞的情景原理分析

我不会在这个小节里重复上面常规场景里的图解,我觉得我只描述UDP打洞场景就好了(我直到现在依然记得江琦博士TCP打洞全世界第一,希望长春Leadwell做SIP的同事见文与我联系,想念你们...)。
       打洞原理非常简单,我假设中心节点是X,而子节点A和子节点C均在NAT之后,那么打洞过程如下图所示,分两步:
第一步:让中心节点X分别记录下A和C的外网地址和端口:




第二步:彼此尝试并最终成功连接




这样,即便子节点处在NAT之后,依然可以建立正常的点对点互联,并且如果二者在同一个NAT后面,还可以建立直连互联,这真是强大!事实上,这种模式早就被我们使用了好多年,伟大的腾讯公司早就使用这种方式运作QQ了。难道QQ不是一种特殊的VPN吗?QQ是什么:
1.QQ对等客户端双方加密通信;
2.QQ自带打洞功能,处在不同NAT后面的客户端依然可以直接建立连接(若真不行,经由服务器中转是补偿方案);
3.QQ自带打洞功能,处在同一NAT后面的客户端可以不经NAT而直连。


3.对协议设计的影响

BadVPN无需在协议中区分控制信息和数据,BadVPN是完全的带外控制,而不像OpenVPN那般的带内控制。
       我们看看BadVPN的数据通道协议,即子节点之间互发数据的协议,非常简单。它经由下图所述的封装即可传输:




因为数据发给谁是“交换机查表”的结果,不会错的,所以无需在接收端进一步判断。接收端收到之后,可以信任一定是发给自己的(当然为了安全起见,还是要判断一下的,但这不是根本)。
       这有点类似于全双工交换式以太网的运作方式,一条网线连接且仅仅连着两台设备,如果这条网线上有流量,那一定是这两台设备之间的流量,如果其中一台设备发出数据,那么接收端一定是网线另一端的设备,这就是点对点全双工通信。
       除了数据通道不再需要中心节点中转,对于控制通道协议而言,我们依然可以看到这里解除控制和数据的耦合后的好处。仅举一例,即子节点之间的密钥协商过程。假设子节点A和B同时连接于中心节点X,当B节点接入后,B要和A之间建立SSL通道,这个SSL通道是SSL中的SSL,分为A到X以及X到B两段,如下图所示:




然后A和B之间的对称密钥就是在这两段的SSL通道中协商出来的。协商方式非常多,可以让A或者B随意一方生成一个密钥,经由A-X-B或者B-X-A的SSL通道传输给B或者A,也可以使用简单的DH算法来直接交换生成密钥,总之,就跟IPSec的IKE两阶段协商一个道理,第一节点通道要为第二阶段提供保护。
       这种事情在OpenVPN就会非常复杂,因为在数据通道层面上,必须将整个控制通道分为不同数据通道的不同控制通道,而不是一个统一的控制通道,因此,对于OpenVPN而言,只能将两种通道彻底分开,然后依靠“类似深度包解析”的方式来判断哪个数据属于哪个通道的控制面还是数据面,从而导致了大量的冗余。这有点类似于数据库表的设计,要通过键沟通的方式来建立关联,而不是把所有数据都塞入一张复杂的大表中:




附:命令行参数解析

我说过,BadVPN是靠点对点的方式完成VPN通信的,那么完成这种通信的基础就是底层的TCP/IP网络,显然需要对五元组。和OpenVPN的理由一样,BadVPN建议使用UDP来作为传输协议以防重传叠加。但是即便是UDP,也要确定哪个4元组不是吗?是的。
       对于在文章《 BadVPN详解之--编译与运行》中的“运行”一节,命令行中的ext-addr参数所指定的IP地址和端口就是VPN数据通信的IP地址和端口,也是上面图示中中心节点向新接入的子节点通告的既已经接入的子节点的IP地址和端口,这个元组是控制通道的元组。
       与ext-addr参数不同的是,中心节点的listen-addr参数以及子节点中的server-addr参数均指代控制通道的数据通信元组。

4.对组网拓扑的影响

BadVPN一开始就是点对点的对等拓扑,中心节点不负责任何数据传输和转发任务,正如其实例文档所述:
NOTE: badvpn-server does not actually participate in the virtual network. If you want the server machine to be part of the network, run a local badvpn-client, like on other peers.
再次看一眼“BadVPN是另一个VPN”小节中的BadVPN总览图,会发现,子节点之间谁也不比谁更重要,大家完全是对等的。所以对于BadVPN而言,拓展整个虚拟子网变得超级容易,就像在一台以太网交换机的一个端口上连接一台主机一样。
       BadVPN在配置中去除了TAP和TUN之间的区分,也不再BadVPN内部配置虚拟网卡的IP地址等。BadVPN直接帮你构建了一个数据通道,该数据通道由一个既已存在的控制通道所控制。所有的子节点均在一个虚拟出来的以太网中,所有人都知道什么是以太网,那就是只要把网线插入交换机,配上IP地址就可以互联互通的网络,BadVPN正是帮你构建了这么一个网络,非常简单!


我的遗憾(纯情感迸发,纯技术者请绕道)

我遗憾自己没有在2015年9月前看到这个BadVPN项目。如果在此之前得知这个项目的话,我可能就不会迷茫,我会继续钻研技术细节而不是什么产品的市场场景,我可能会重构BadVPN而不是不可救药的OpenVPN。
       但是一切都太晚了。我于2015年9月份放弃了自己的OpenVPN项目,背井离乡来到了一个对自己而言非常陌生的地方深圳,这里拥有来自全国各地(两湖两广居多)怀着激情和梦想的年轻人(以在大城市买房置业为目标),却连一条像样的快速路都没有(不拿堵车说事,深圳的快速路高架桥完全不敌广州,上海,毫无规划,基本也就是见招拆招),产业更是出其不意的单调,但这里的人却无比喜欢自己生活的城市,也是是他们大多数从自己的家乡到武汉等地上大学然后就到了深圳没在别的地方生活过的缘故吧,说实话,像我这种以文化享受为己任的多元化人,并不喜欢深圳这座城市。但是就因为我没有在正确的时间接触到BadVPN,导致了我无力进一步深挖VPN的架构,具有讽刺意味的是,我现在也成了深圳人,也开始喜欢上了这个地方,和我的性格比较类似,如果我不喜欢深圳的道路,那么我来自己建设它,所以如果我不干IT了,我希望能成为深圳的城市规划者,当然,这是后话。
       小小长大了,要在深圳上小学了,我很欣慰诸多喜欢我的读者也在关注着小小一天天地长大,曾经有人告诉我他看过我写的一篇关于VPN的文章,那时我记录了小小的出生,那是2011年6月28日小小出生的第二天,我写那篇文章的时候,我正休着陪产假,换班时在家里写了那篇文章,这篇文章是《 Linux的Netfilter框架深度思考-对比Cisco的ACL-》。
       后来为了小小在上海买了房子,在我的第一座一线城市的房子里,想了太多的关于OpenVPN的点滴,也分享了很多,我很怀念我家的榻榻米,同时必须要感谢关注我的每一个人。现如今,深夜里我坐在深圳的窗下,正在下雨,非常爽,但是我很遗憾,我没有及时意识到BadVPN的存在,我甚至无法把OpenVPN发扬光大,在无所事事的时候误入了歧途。但我相信,总有一天我会回去做我喜欢的东西的,虽然我为了把房子租出去而丢弃了榻榻米换成了床,如果我回去,我还是会换回去的,哪怕只是为了情怀!记得那个时候,小小蹒跚学步,呀呀学语...我深深的知道,如果有一天我回到了上海的家,再次遇到了我的好邻居,我的好朋友,也许我可以再次和他们一起喝酒吹牛,但再也没有小小小时候伴随的的快乐了。
......

我曾经的c2c组网方案

OpenVPN的主从模式限制了OpenVPN的组网灵活性。有一个实际的需求是建立N个VPN节点间的对等通信,这在BadVPN看来就是一个原始的配置,N个子节点同时连接中心节点即可,这样它们就自然而然建立了对等的P2P拓扑,然而如果使用OpenVPN,便不然。OpenVPN的方案需要太多额外的支持,比如要用Bonding,Bridge,iproute2,Policy routing,iptables,ebtables等工具助力完成配置,过程及其复杂。
       这里只设一个题目,如下A,B,C三个节点需要建立对等的点对点连接,该如何?由于OpenVPN必须采用主从模式,那么A,B,C三点必须采用咬尾巴蛇的策略来建立互通,如下图所示:




显然很合理。那么如果是四个节点,五个节点,甚至更多的节点呢?显然环形的咬尾巴蛇策略就不可行了,那么要实现两两互通那该怎么办?典型且直接的方案就是每一个VPN节点均运行一个中心节点模式VPN,再运行N-1个子节点模式VPN,这样便可以彼此互通:




拓扑是搞定了,还挺和谐对称(PS:这是一个真实的案例拓扑,目前依然在一个规模想当的城域网上运行着)。然而你考虑以下的问题了吗:
1.一个VPN节点上要创建多少tap虚拟网卡?
2.如何实现多个节点间流量的隔离?
3.由于每个节点均运行一个中心节点模式的VPN,那么策略怎么推送?
4.要配置多少Policy routing路由,用以支持不同的子网之间的互通和隔离?
5.要想完成上述第4点,需要配置多少iptables规则?
...

我相信,上面的清单要是列出来,很少有人可以瞬间理清头绪的。我记得当时我在做这个产品的时候,曾经无数次的跟同事阐述以上这些原理,最终都是无果而终,最终的最终,我自己都已然忘却,在我从OpenVPN相关的项目组离开后直到现在,有很多人问起过我关于OpenVPN的问题,恕不能答,因为我自己也理不清了...我每次都要看我之前写的那些博客或者笔记才能明白到底是怎么一回事,唉。总之,罪魁祸首就是OpenVPN的主从模式导致组网太复杂了。
       如果使用BadVPN,则基本没有这么一回事了。BadVPN在搭建好之后,就是点对点的,无须设置任何规则即可所有节点互联互通:




-----------------------------------------------
好了,以上就是BadVPN的大部分原理知识了。如果你还是不理解,请继续听我下回分解,在下文中,我将讲述一个我自研的一个设计。该设计可能比较垃圾,也可能比较比较爆款,但不管怎样是我的真情实感,在我遇上BadVPN之前就思考了一段时间,最终看到Badvpn之后,发现确实如此的相类似。
       不是英雄所见略同,而是正确的道路往往只有很少的几条。且听下回分解!

           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

猜你喜欢

转载自blog.csdn.net/gdfhhj/article/details/83987723
今日推荐