网络去中心化技术p2p架构之网络穿透
实现NAT网络穿透打洞首先需要判断NAT网关类型,判断逻辑如下:
1.先判断网关是对称型NAT还是锥型NAT;
同一个client socket给两个server 120.94.23.180:2230;120.94.23.180:2234发送消息;server1把获取到的client IP地址发给server2,server2来对比这两个网关的IP地址是否是一样,如果一样是锥形NAT[走逻辑2的判断流程],不一样是对称NAT;
锥形NAT client只有一个端口对外使用,但会与不同的目的地址及端口生成记录表中的不同的记录。
2.判断网关是完全锥型NAT还是限制性锥型NAT;
cliecnt先给server1发送消息,server1把获取到的client IP地址发送给server2,server2直接给网关发送数据,client如果没有收到数据,隔很长一段时间由client再次启动一次,启动三次,仍然没有收到数据,这是判断是IP限制型锥型NAT;如果client收到数据,判断为完全锥型NAT。
3.在流程2的前提下,判断判断网关是否是端口限制型锥型NAT;
在同一台server中开两个端口120.94.23.180:2234;120.94.23.180:2230;同一个client socket给120.94.23.180:2234发送数据,server收到数据后再通过120.94.23.180:2230给client端发送响应数据,如果client没有收到数据,判断是端口限制型锥型NAT。
做网络穿透时有限采用UDP协议,因为UDP sendto()时可以直接带目的IP地址。
采用UDP实现网络高并发。多个client端给server UDP 8080端口发送数据,也就是说server sockfd 会收到不同客户端发送的数据。当client1 sendto()给server 端8080端口发送数据,Server端 recvfrom()可以获取到这个客户端网关的IP地址和端口号,当收到clent1的数据后server重新创建一个socket,再绑定本地的另外一个端口,创建一个fd,通过这个端口sendto()给client1发送数据。这时server每一个socket都会和client形成一对一的关系。这里server每创建一个socket都交给epoll来管理。当端口不够用了,端口复用,只需保证五元组不重复就可以了。注意当网关是对称型NAT(虽然是同一台server的不同端口,网关上记录表没有生成与server端新的端口的记录)或者是端口限制型NAT,client会收不到server发送的报文数据,导致网络穿透失败。
网络穿透
A to B网络穿透共4*4=16种NAT搭配组合可归类为3种
1.两边任意一边是完全锥形NAT(8种组合搭配),这时是完全可以穿透的。
分为4个步骤:
步骤1:client1发送数据给server请求与client2通信,server获取到client1的公网ip和端口号;
步骤2:server发送数据通知client2,数据报文内容包含client1的公网ip和端口号;
步骤3:client2发送数据给client1进行网络穿透打洞,client1可以收到client2的数据并获取到client2的公网ip和端口号;
步骤4:client1发送数据给client2,client2可以收到来自client1的数据,网络穿透成功。
2.两边都是限制性NAT(4种组合搭配),这种情况是可以穿透的;
两边都是限制型NAT组合的网络穿透分为7个步骤:
步骤1:clientA发送报文给server,server获取到clientA的公网IP和端口号;
步骤2:server发送通知报文{获取到clientA的公网IP,端口号}给clientB;
步骤3:clientB发送报文给clientA的公网IP和端口号,探测尝试穿透,但是clientA所在的NATA是限制型锥型NAT,因此clientA此时不能收到clientB发送的报文数据;
步骤4:clientB发送报文给server,server获取到clientB的公网IP和端口号;
步骤5:server发送通知报文{获取到clientB的公网IP,端口号}给clientA;
步骤6:由clientA发送报文给clientB的公网IP和端口号,进行网络穿透,由于步骤3,NATB路由器上记录表已生成记录,这时clientB是可以收到clientA发送的报文数据,NATB网络穿透成功;
步骤7:clientB再次发送报文给clientA的公网IP和端口号,这时NATA路由器上记录表也已经生成记录,clientA是可以收到clientB发送的报文数据,NATA网络穿透成功;
3.对称NAT与限制型NAT的组合(4种组合搭配),对称NAT穿透不了,这种NAT组合穿透比较麻烦。对称NAT的client端接收到数据,进行第3步穿透时会重新分配新的端口号,不能直接穿透。端口预测打孔,需要猜测对称NAT网关在第三步生成的记录,client2再次给服务器发送消息,生成第三条记录,服务器将两条记录发送给client1,client猜测网络穿透第三步生成的记录端口号,如果这个端口号在服务器返回的两条记录端口号区间内,则可以穿透
限制型锥型NAT和对称NAT组合的网络穿透分为7个步骤:
步骤1:clientA发送报文给server请求与clientB进行透传,server获取到clientA的公网IP和端口号;
步骤2:server发送通知报文{获取到clientA的公网IP,端口号}给clientB;
步骤3:clientB发送报文给clientA的公网IP和端口号,探测尝试穿透,由于NATB是对称NAT,所以在报文发送经过NATB路由器会生成新的映射记录,并且分配新的{112.92.114.23,端口号5000};但是NATA是限制型锥型NAT,因此clientA此时不能收到clientB发送的报文数据;
步骤4:clientB发送报文数据给server的另一个端口8000,NATB路由器会生成新的映射记录,并且分配新的{公网IP地址112.92.114.23,端口号5005};server获取到clientB的另一个{公网IP地址112.92.114.23,端口号5005};
步骤5:由server的另一个端口8000端口发送通知报文{公网IP地址112.92.114.23,端口号5005}给clientA,可以用来猜测判断步骤3 中clientB产生的{公网IP,端口号},根据路由器分配端口号的策略得知步骤3 中clientB产生的{公网IP,端口号}的5000端口号在记录表端口号4347和端口号5005区间内[记录表端口号4347是在步骤3之前产生的];
步骤6:由clientA发送报文给clientB的公网IP和猜测端口号,进行网络穿透,如果猜测端口号命中,即找到5000端口,clientA发送报文数据到{112.92.114.23,5000},clientB是可以收到clientA发送的报文数据,NATB网络穿透成功;
步骤7:clientB再次发送报文给clientA的公网IP和端口号,clientA是可以收到clientB发送的报文数据,NATA网络穿透成功;
解决UDP在空闲状态下的超时的问题:
多数NAT设备内部都有一个UDP转换的空闲状态计时器,如果在一段时间内没有UDP数据通信,NAT设备会关掉由“打洞”过程打出来的“洞”。穿透后通过keepalive心跳包维持连接,来解决UDP在空闲状态下的超时。
拔掉网线,客户端网络全部会被回收,再次插上,网卡重新启动,网关进行重连IP和端口号会被重新分配。