P2P的NAT穿透解析

2018-12-12  本文已影响0人  tristan_lee

[TOC]

NAT背景

NAT(Network Address Translation,),称为网络地址转换或者网络地址掩蔽。NAT是一种网络地址翻译技术,主要是将内部的私有IP地址(private IP)转换成可以在公网使用的公网IP(public IP)。

由于现有的IPv4地址编码只有32位空间,最多可容纳2的32次幂台终端设备连入互联网;再加上IPv4地址空间被按照不同前缀长度划分为A,B,C,D类地址网络和保留地址,更加剧了IP地址的不足。NAT出现的背景正是源于IPv4地址不够用,所以才会采取这种地址转换的策略。可见,NAT的本质就是让一群机器共用同一个IP,这种方案暂时解决了IP短缺的问题。

NAT类型

在RFC3489中定义了4种NAT类型(如下),即早期的STUN协议。STUN(Simple Traversal of User Datagram Protocol Through Network Address Translators),即简单的用UDP穿透NAT,是个轻量级的协议,是基于UDP的完整的穿透NAT的解决方案,最早定义在RFC3489。它允许应用程序发现它们与公共互联网之间存在的NAT和防火墙及其他类型。后来在新的RFC5389修订中把STUN协议定位于为穿透NAT提供工具,而不是一个完整的解决方案,英文全称为Session Traversal Utilities for NAT,即NAT会话穿透工具。

完全锥型NAT 受限锥型NAT 端口受限型NAT 对称型NAT

NAT穿透之UDP打洞

UDP打洞技术是通过中间服务器的协助在各自的NAT网关上建立相关的表项,使P2P连接的双方发送的报文能够直接穿透对方的NAT网关,从而实现P2P客户端互连。如果两台位于NAT设备后面的P2P客户端希望在自己的NAT网关上打个洞,那么他们需要一个协助者——中间服务器,并且还需要一种用于打洞的Session建立机制。目前通用的就是使用STUN协议。

P2P建立Session的通用过程

假定客户端A要发起对客户端B的直接连接,具体的“打洞”过程如下:

  1. A最初不知道如何向客户端B发起连接,于是A向集中服务器发送消息,请求中间服务器S帮助建立与客户端B的UDP连接。
  2. 中间服务器S将含有B的外网和内网的地址二元组发给A,同时,中间服务器S将包含有A的外网和内网的地址二元组信息的消息也发给B。这样一来, A与B就都知道对方外网和内网的地址二元组信息了。
  3. 当A收到由中间服务器S发来的包含B的外网和内网的地址二元组信息后, A开始向B的地址二元组发送UDP数据包,并且A会自动锁定第一个给出响应的B的地址二元组。同理,当B收到由中间服务器S发来的A的外网和内网地址二元组信息后,也会开始向A的外网和内网的地址二元组发送UDP数据包,并且自动锁定第一个得到A回应的地址二元组。由于A与B互相向对方发送UDP数据包的操作是异步的,所以A和B发送数据包的时间先后并没有时序要求。

P2P的3种典型NAT穿透场景

场景1
1. A向中间服务器S请求与B进行连接,S将B的外网以及内网的地址二元组发给A
2. 中间服务器S把A的外网以及内网的地址二元组信息发给B
3. A和B各自给对方公网以及内网地址二元组信息各发送UDP数据包
4. 选择最先响应的地址二元组信息进行常规P2P通信

我们注意到这时里的公网地址其实只有一个,只是目标端口不同。往公网地址发送的UDP数据如果想成功穿透,NAT设备需要支持Hairpin技术。Hairpin技术又被称为Hairpin NAT、Loopback NAT或Hairpin Translation。它能够让两台位于同一台NAT设备后面的主机,通过对方的公网地址和端口相互访问,NAT设备会根据一系列规则,将对内部主机发往其NAT公网IP地址的报文进行转换,并从私网接口发送给目标主机,类似一种中继(relay)。目前有很多NAT设备不支持该技术,这种情况下,NAT网关在一些特定场合下将会阻断P2P穿越NAT的行为,打洞的尝试是无法成功的。

场景2
1. A向中间服务器S请求与B进行连接,S将B的外网以及内网的地址二元组发给A
2. 中间服务器S把A的外网以及内网的地址二元组信息发给B
3. A和B各自给对方公网以及内网地址二元组信息各发送UDP数据包
4. 由于内网不存在对端机器,所以内网不会有响应,只有外网响应后才可以通信
场景3

假定NAT C是由ISP提供的NAT设备,NAT C提供将多个用户节点映射到有限的几个公网IP的服务,NAT A和NAT B作为NAT C的内网节点将把用户的内部网络接入NAT C的内网,用户的内部网络就可以经由NAT C访问公网了。从这种拓扑结构上来看,只有服务器S与NAT C是真正拥有公网可路由IP地址的设备,而NAT A和NAT B所使用的公网IP地址,实际上是由ISP服务提供商设定的(相对于NAT C而言)内网地址(我们将这种由ISP提供的内网地址称之为“伪”公网地址)。同理,隶属于NAT A与NAT B的客户端,它们处于NAT A,NAT B的内网,以此类推,客户端可以放到到多层NAT设备后面。客户端A和客户端B发起对服务器S的连接的时候,就会依次在NAT A和NAT B上建立向外的Session,而NAT A、NAT B要联入公网的时候,会在NAT C上再建立向外的Session。

现在假定客户端A和B希望通过UDP“打洞”完成两个客户端的P2P直连。最优化的路由策略是客户端A向客户端B的“伪公网”IP上发送数据包,即ISP服务提供商指定的内网IP,NAT B的“伪”公网地址二元组,{10.0.1.2:55000}。由于从服务器S的角度只能观察到真正的公网地址,也就是NAT A,NAT B在NAT C建立session的真正的公网地址{155.99.25.11:62000}以及{155.99.25.11:62005},非常不幸的是客户端A与客户端B是无法通过服务器S知道这些“伪”公网的地址,而且即使客户端A和B通过某种手段可以得到NAT A和NAT B的“伪”公网地址,我们仍然不建议采用上述的“最优化”的打洞方式,这是因为这些地址是由ISP服务提供商提供的或许会存在与客户端本身所在的内网地址重复的可能性(例如:NAT A的内网的IP地址域恰好与NAT A在NAT C的“伪”公网IP地址域重复,这样就会导致打洞数据包无法发出的问题)。

因此客户端别无选择,只能使用由公网服务器S观察到的A,B的公网地址二元组进行“打洞”操作,用于“打洞”的数据包将由NAT C进行转发,此时如果NAT C不支持Hairpin转换,打洞将失败。

P2P做NAT穿透的约束条件

全文完

参考资料

Peer-to-Peer Communication Across NATs

上一篇 下一篇

猜你喜欢

热点阅读