NAT穿越方案目前有:
- STUN
- TURN
- ICE
- 其它技术:ALG、UPnP、Midcom、Full Proxy
区别:
- TURN、STUN、ICE都是应用程序提供的解决方案,不依赖于硬件设备;
- TURN、STURN的共同点都是通过修改应用层中的私网地址达到NAT穿透的效果,异同点是TURN是通过两方通讯的“中间人”方式实现穿透。
- ICE跟STUN和TURN不一样,ICE不是一种协议,而是一个框架(Framework),它整合了STUN和TURN,可以穿越任何nat设备。
- ALG、UPnP属于设备提供的方案,依赖于各个终端NAT设备的支持。
1. STUN
STUN的全称是Simple Traversal of UDP Through Network Address Translators,即穿越NAT的简单UDP传输。
它允许应用程序发现自己和公网之间的NAT类型,同时也能允许应用程序通过STUN服务器发现自己被NAT分配的公网IP,这些信息被用来在两个同时处于NAT [路由器]之后的[主机]之间建立UDP通信。
- 优点:是无需改变nat/fw,只需要应用程序支持stun协议。
- 缺点:不支持对防火墙和对称NAT的穿越
2.turn
Traversal Using Relays around NAT,即采用中继器的NAT穿越,也叫中转方式(Relay)
与stun方式类似采用客户端服务器模式,但是内网主机的公共地址是服务器分配的,内网主机发送的报文都要经过Turn服务器进行中继转发,即集中式的拓扑结构。
优点是可以解决stun无法穿越对称式nat,也支持tcp。
缺点是当数据量大时,服务器的并发和处理能力成为瓶颈,且增大了包的延迟和丢包的可能性。
stun是对中间服务器轻依赖的,可是存在部分无法穿越问题;
turn对中间服务器强依赖,但是可以穿越所有nat;
可以想到一种理想的方式,stun可以穿越的主机使用stun,stun无法穿越的部分使用turn,两者结合。
这正是ice要做的事情,讲起来简单,其实ice的真正实现比这个复杂太多。
3.ice方式
ICE(Interactive Connectivity Establishment)交互式连接建立方式,结合了stun,turn等协议来提供一个通用的解决方案。是被认为在非对称NAT环境下首选的NAT穿越解决方案。由于该技术不需要为VoIP流量手动打开防火墙,所以也不会产生潜在的安全隐患。
image.png
如上图所示,如果A想与B通信,那么其过程如下:
(1)A收集所有的IP地址,并找出其中可以从STUN服务器和TURN服务器收到流量的地址;
(2)A向STUN服务器发送一份地址列表,然后按照排序的地址列表向B发送启动信息,目的是实现节点间的通信;
(3)B向启动信息中的每一个地址发送一条STUN请求;
(4)A将第一条接收到的STUN请求的回复信息发送给B;
(5)B接到STUN回复后,从中找出那些可在A和B之间实现通信的地址;
(6)利用列表中的排序列最高的地址进一步的设备间通信;
4. UPnP
路由器要支持UPnP并开启
拓展:那种穿越方式最适合区块链项目?
答案是:
IETF规范
- RFC3489中定义STUN,作为一个完整的NAT穿透解决方案,英文全称是Simple Traversal of UDP Through NATs,即简单的用UDP穿透NAT。
- RFC5389新修订中把STUN协议定位于为穿透NAT提供工具,而不是一个完整的解决方案,英文全称是Session Traversal Utilities for NAT,即NAT会话穿透效用,除了名称变化外,最大的区别是支持TCP穿透。
- RFC5766中定义TURN,英文全称是Traversal Using Relays around NAT:Relay Extensions to Session Traversal Utilities for NAT,即使用中继穿透NAT
- RFC 5245: Interactive Connectivity Establishment (ICE): A Protocol for NAT Traversal for Offer/Answer Protocols.
- RFC 6544: TCP Candidates with Interactive Connectivity Establishment (ICE)
TCP与UDP穿越
UDP是主流的NAT穿越协议,比起TCP穿越成功率要高很多,因为大部分NAT设备不支持TCP的丢包处理。
反观UDP打洞技术,缺点是无法穿越对称形NAT,虽然可以使用端口预测的UDP穿越(因为NAT设备对端口的随机分配是规律性的),但是失败率也很高。
UDP
image.pngTCP
image.pngTCP/UDP穿越测试结果对比
image.png问题1:tcp打洞与udp打洞的区别
-
会话时效问题
通常TCP会话通过协商的方式主动关闭连接,NAT网关可以跟踪这些报文,在会话结束时回收资源,清除关联表。
而基于UDP的通信协议很难确定何时通信结束,所以NAT网关主要依赖超时机制回收外部端口,一般是15-20秒,但是这样做会引发很多连接中断、找不到目标等问题,双方必须不断发送心跳以保持会话。 -
连接问题
udp只需要向对方发送一次报文,就可以完成打洞,两边不需要建立连接,只要在有效的会话期间内(15-20s)完成打洞可以。
tcp通信是需要建立连接的,连接过程中,监听的同时异步地向对方发送sync包,等待对方回复ack包。如果双发请求监听的失效不一致可能会导致连接失败,这时候需要设置延迟连接和重试。
-
套接字(socket)和端口绑定问题
udp一个socket可以与多台主机的通信,建立1对多的连接;
tcp是基于客户端服务器的,一般一个端口只能绑定一个socket,且只能建立1对1的连接。要建立1对多,需要使用“SO_REUSEADDR”允许应用程序将多个socket绑定到一个端口。 -
NAT的支持问题
UDP穿越,首先需要知道终端的NAT类型(4种类型),实际上就是需要NAT设备对端口映射必须一致,同一个内网地址和端口建立的连接映射成相同的公网地址和端口,UDP不支持对称形NAT(Symmertric NAT)穿越;
TCP穿越需要NAT设备支持对来着公网SYN包的丢弃处理,就是什么都不做。因为有的NAT设备收到没有映射关系的公网SYN包会向源端发送ICMP错误响应,源端收到后会直接导致TCP连接失败;
目前的NAT路由器设备,UDP协议比TCP协议更容易穿越成功。
问题2:同个局域网的主机进行p2p通信,如何避免hairpin问题
hairpin 路由回路 端口回路 回环NAT
案例证明了这一点:
geth私有链,内网两台电脑节点可以通过addPeer互相发现;
geth共有链,内网两台电脑节点不管是手动或者自动都无法发现对方;
问题3:p2p连接后的鉴权问题
因为nat的问题,ip+端口是动态分配、可变的,甚至还有session失效,无法作为固定的主机路由。比如局域网的两台主机很可能会交替使用相同的外网ip和端口出去,对于外网来说这些是不可预测的。
所以,P2P连接上,进行内容通信前,做鉴权操作,确定目前连入的主机是所希望的。
案例:
以太坊的节点id:encode:dfdfd@139.32.33.1:30030
dddd其实是节点的公钥,以太坊是用ECKey椭圆曲线算法来生成密钥对,私钥节点自身保持,公钥则作为节点id的一部分发给与之连接的所有节点,节点A给节点B发送信息前,先用B的公钥给信息加密,密文只有真正持有秘钥的B才能解密,从而保证了数据传输的准确性和安全性;
网友评论