Liquid对于复杂网络环境适应性的提升

 1.前  言 

Liquid是长安链自研网络模块。和libp2p相比具备更加精简、针对区块链系统效率更高、自主可控等优点。为了增加Liquid应对复杂网络的适应性,新增了节点中继和NAT穿透功能,提升了其在特定网络环境中的组网建联能力。

 2.适用场景 

比如我们有两个机房,每个机房是一个独立的局域网环境,他们可以连接公网,但是没有公网域名,无法通过dns或其他方式“暴露”自己。同时有防火墙阻拦,即便获知了该局域网的公网ip也很难直连,因为很多时候不能为每个局域网内的节点都开放一个端口。如下图所示:

图1

但是如果使用节点中继或NAT穿透,就可以在不额外修改防火墙策略,且没有dns获取外网地址的情况下,完成两个私有局域网的节点建联,下面分别讲述节点中继或NAT穿透。

 3.节点中继 

3.1功能概述

当两个节点因为网络环境的原因,不能直接连接,可以搭建一个中继节点,对流量数据进行转发,从而达到点对点传输的效果。

图2

图片中的绿线是一条中继通道,当局域网B中的节点要向局域网A中的节点发送消息时,通过云服务器进行中继转发。同理局域网A中的节点要向局域网B中的节点发送消息时,也可以通过云服务器完成消息中继转发。

3.2 Relay的基本流程

假设网络中有AB两个节点,分别部署在不同的局域网中。中继节点为R,A节点可以拨号连接到中继节点R,B节点可以拨号连接到中继节点R,A节点通过中继节点R,将数据转发到B节点,这样使A和B节点也能做到数据交互。具体步骤如下:

步骤一:开启一个中继请求的stream(A到R)

1)A使用协议“liquid-relay”向R拨号建立新的stream“sAR”;

2)A通过“sAR”发送中继消息`{ type: 'HOP', srcPeer: '/p2p/QmA', dstPeer: '/p2p/QmB' }`;

3)R通过“sAR”stream读取消息。

步骤二:开启一个中继请求的stream(R到B)

1)R使用协议“liquid-relay”向B打开新的stream“sRB”;

2)A通过“sRB”发送中继消息`{ type: 'STOP', srcPeer: '/p2p/QmA', dstPeer: '/p2p/QmB' }`;

3)R通过“sAR”发送中继消息`{ type: 'STATUS', code: 'SUCCESS' }` 。

步骤三:流通过管道连接在一起,形成一个回路

1)B通过stream“sRB”接收消息;

2)B通过“sRB”发送中继消息 `{ type: 'STATUS', code: 'SUCCESS' }` ;

3)B将流传递给`NewConnHandler`,像任何其他新的传入连接一样进行处理。

在区块链中我们需要遵循任何事物都是不可信的原则,中继节点也不例外。中继节点作为转发者,肯定是不能允许其有作恶能力的。我们通过以下两点防止中继节点作恶:

1. 中继节点本身就属于网络成员,需要跟其他节点tls握手建立连接才能工作;
2. 中继过程属于端到端加密的,也就是被中继节点之间的数据传输还是加密的,中继节点只是负责转发加密后的密文。

综上所述,具体的中继流程图如下:

图3

 4.NAT穿透 

4.1功能概述

NAT穿透(NAT traversal)可以简单理解为:在不额外修改NAT策略的情况下(例如:开启某个端口对外可用),处于使用了NAT设备的不同私有网络中的主机之间建立网络连接。

我们这一章节所说的NAT穿透,可以理解为使用“打洞”的方式实现NAT穿透。

4.2 NAT简介

NAT(Net Address Translation):网络地址转换。它的作用是把内网的私有地址,转化成外网的公有地址。使得内部网络上的(被设置为私有IP地址的)主机可以访问Internet。

NAT的效果包括但不限于:

①多个内网设备公用一个外网地址,节省外网地址个数。这一作用在ipv6诞生之前有较强的实用性;

②可以设置安全策略,防止外网请求直接进入内网环境。

NAT可以分为下面几种类型:

1.Full Cone NAT

完全锥形NAT,所有从同一个内网IP和端口号发送过来的请求都会被映射成同一个外网IP和端口号,并且任何一个外网主机都可以通过这个映射的外网IP和端口号向这台内网主机发送包。

2.Restricted Cone NAT

限制锥形NAT,它也是所有从同一个内网IP和端口号发送过来的请求都会被映射成同一个外网IP和端口号。与完全锥形不同的是,外网主机只能够向先前已经向它发送过数据包的内网主机发送包。

3.Port Restricted Cone NAT

端口限制锥形NAT,与限制锥形NAT很相似,只不过它包括端口号。也就是说,一台IP地址X和端口P的外网主机想给内网主机发送包,必须是这台内网主机先前已经给这个IP地址X和端口P发送过数据包。

4.Symmetric NAT

对称NAT,所有从同一个内网IP和端口号发送到一个特定的目的IP和端口号的请求,都会被映射到同一个IP和端口号。如果同一台主机使用相同的源地址和端口号发送包,但是发往不同的目的地,NAT将会使用不同的映射。此外,只有收到数据的外网主机才可以反过来向内网主机发送包。

图4

4.3 NAT类型对穿透性的影响

两个主机所在的NAT类型的组合,会影响其穿透性。

但是只有两种组合无法正常NAT穿透:①端口受限型-对称型 ②对称型-对称型 。不同组合和其穿透性的对应关系如下图:

图5

4.4 Liquid 实现NAT穿透

Liquid目前支持两种网络协议:tcp(包括tls)和quic。在这两种协议上都集成了NAT穿透功能。

Liquid使用打洞实现NAT穿透需要具备以下前提条件:(tls需要额外处理握手问题)

①每个连接listen的端口,同时也需要是拨号时该连接绑定的端口。即端口复用;

②发现对方的外网地址。

Liquid的节点发现功能很好的满足了第二个条件,下面介绍端口复用。

  • quic(udp)实现端口复用:

端口复用这个条件对于udp和quic来讲是天生支持的。

udp可以简单理解为:处于传输层的udp协议收到一个远端发来的udp报文后直接返回给应用层。同时应用层发送一个udp报文给传输层时,udp协议几乎不做处理的发给ip层。

这种无连接的方式允许一个udp连接在一个端口上随意收发消息。所以udp几乎是默认端口复用的。基于udp协议的quic也允许端口复用。

  • Tcp实现端口复用:

Tcp是面向连接的协议,端口一定程度上可以标识一个连接。但是操作系统支持我们配置一个tcp连接复用端口。配置端口复用的伪代码如下:

c++伪代码:

golang伪代码:

完成了端口复用,再配合节点发现功能,Liquid已经拥有了NAT穿透功能。但是Liquid还可用通过配置强化其穿透性。Liquid可以通过配置使拨号异步执行,同时listen对方发现的端口。这两个操作不仅提升了打洞速度,还是解决了端口冲突情况下的NAT穿透问题。

4.5 Liquid的NAT穿透(打洞)过程

Liquid的节点发现功能一定程度上代替了STUN协议。最终Liquid的NAT穿透过程大概分为下面几个步骤:

1)通过节点发现功能,发现对方节点地址;

2)向对方节点发送建连请求;

3)等待对方同时发送建联请求,完成打洞。

图6

 5. 总  结 

Liquid同时具备节点中继和NAT穿透(打洞方式)两种功能,可以同时使用其中一种或两种方式实现建联,使用者可以根据实际情况灵活搭配。NAT穿透已经完全集成在Liquid的network中,使用者甚至无需配置。节点中继只需要像libp2p一样,在地址中增加“relay/中继节点地址” 一条信息,Liquid就会自动识别该中继地址,完成整个建联。可以说Liquid让使用者用最简练的配置操作,就能提升了整个网络模块对复杂网络环境的适应性。

猜你喜欢

转载自blog.csdn.net/weixin_55760491/article/details/127616085