一、 P2P

P2P(peer to peer)是一个“点对点传输技术”,也就是两台计算机之间不需要第三台机器作为服务端就能实现数据的传输,每台计算机即是客户端又是服务端。

如果每台计算机都有自己的独立的公网 IP,那么 P2P 技术就比较好实现了,但是现实中由于 NAT(Network Address Translation) 的存在,使得 P2P 技术最大的难点就在于穿越 NAT 的限制,俗称“打洞”。

二、 NAT

2.1 NAT 的产生背景

如果我们把 Internet 比作一个邮政系统,那么 IP 地址的作用就等同于包含城市、街区、门牌编号在内的精确地址,通过 IP 地址可以准确的定位到具体的一台计算机。

IPv4 使用 32bits 整数表达一个地址,地址最大范围就是 232 约为 43 亿。以 IP 创始时期可以联网的设备数量来看,这样的一个空间已经很大,很难被短时间用完。然而,事实远远超出人们的设想,计算机网络在此后的几十年里迅速壮大,网络终端数量也呈爆炸性增长。

更为糟糕的是,为了路由和管理方便,43 亿的地址空间被按照不同前缀长度划分为 A,B,C,D 类地址网络和保留地址。IANA 向超大型企业/组织分配 A 类网络地址,一次一段。向中型企业或教育机构分配 B 类网络地址,一次一段。这样一种分配策略使得 IP 地址浪费很严重,很多被分配出去的地址没有真实被利用,地址消耗很快。以至于二十世纪 90 年代初,网络专家们意识到,这样大手大脚下去,IPv4 地址很快就要耗光了。于是,人们开始考虑 IPv4 的替代方案,同时采取一系列的措施来减缓 IPv4 地址的消耗。正是在这样一个背景之下,NAT 应运而生。

IPv4 即网际网协议第 4 版——Internet Protocol Version 4 的缩写。

2.2 NAT

NAT(Network Address Translation)网络地址转换,就是在内网 IP 和公网 IP 之前相互转换。NAT 通常部署在一个组织的网络出口位置。

2.2.1 内部网络地址

内部网络地址即内网 IP。

RFC1918 规定了三个保留地址段落,这三个范围分别处于 A,B,C 类的地址段,不向特定的用户分配,被 IANA 作为私有地址保留,这些地址可以在任何组织或企业内部使用。

和其他 IPv4 地址的区别就是,其仅能在内部使用,不能作为公网 IP。也就是说,出了组织的管理范围这些地址就不再有意义,无论是作为源地址,还是目的地址。对于一个封闭的组织,如果其网络不连接到外部 Internet,就可以使用这些地址而不用向 IANA 提出申请,在内网使用私有IP地址进行路由管理和报文传递的方式与其他网络没有差异。

三类地址段中的私有IP地址段分别如下:

1
2
3
10.0.0.0 ~ 10.255.255.255      即 10.0.0.0/8
172.16.0.0 ~ 172.31.255.255 即 172.16.0.0/12
192.168.0.0 ~ 192.168.255.255 即 192.168.0.0/16

对于有 Internet 访问需求而在内部却使用私有地址的网络(目前绝大多数网络都是这样),就要在组织的出口位置部署 NAT 网关,在报文离开私网进入 Internet 时,将源 IP 替换为公网地址,通常是出口设备的接口地址。

一个对外的访问请求在到达目标以后,在目标看来是由本组织的出口网关所发起,因此被请求的目标将响应内容由 Internet 发回到出口网关。出口网关再将目的地址替换为私网的源主机地址和端口,发回内部(网关是如何将不同的响应替换成响应的私有IP和端口的呢?请看下一节)。这样一次由私网主机向公网服务端的请求和响应就在通信两端均无感知的情况下完成了。依据这种模型,数量庞大的内网主机就不再需要公有 IP 地址了。

需要注意,在一个网络中可以有多个NAT网关,也可以出现网关套网关的情况,内层网关可以没有公网IP。

2.2.2 NAT 分类

  1. 全锥形 NAT(Full Cone NAT)
    一旦内部主机端口对(iAddr:iPort)被 NAT 网关映射到(eAddr:ePort),所有后续的(iAddr:iPort)报文都会被转换为(eAddr:ePort);任何一个外部主机发送到(eAddr:ePort)的报文也将会被转换后发到(iAddr:iPort)。

  2. 限制锥形 NAT(Restricted Cone NAT)
    一旦内部主机端口对(iAddr:iPort)被映射到(eAddr:ePort),所有后续的(iAddr:iPort)报文都会被转换为(eAddr:ePort);但只有 (iAddr:iPort)向特定的外部主机 hAddr 发送过数据后,主机 hAddr 从任意端口发送到(eAddr:ePort)的报文将会被转发到(iAddr:iPort)。

  3. 端口限制锥形 NAT(Port Restricted Cone NAT)
    一旦内部主机端口对(iAddr:iPort)被映射到(eAddr:ePort),所有后续的(iAddr:iPort)报文都会被转换为(eAddr:ePort);但只有(iAddr:iPort)向特定的外部主机端口对(hAddr:hPort)发送过数据后,由 (hAddr:hPort)发送到(eAddr:ePort)的报文才会被转发到(iAddr:iPort)。

  4. 对称型 NAT(Symmetric NAT)
    内部主机“地址端口对”(iAddr:iPort)请求特定外部主机“地址端口对”(iAddr:iPort)时,NAT 网关都会映射一个特有的(eAddr:ePort)。只有收到报文的外部主机从对应的端口对发送回应的报文,才能被转换。即使内部主机使用之前用过的“地址端口对”去连接不同外部主机(或端口)时,NAT 网关也会建立新的映射关系。

从上面描述可以看出,不同的NAT类型的安全性系数依次为 对称型 > 端口受限锥型 > 受限锥型 > 全锥型,同样NAT穿越的难度也是依次降低。

三、 NAT 穿越技术

常见的 NAT 穿越技术有:STUN、TURN、ICE。

3.1 STUN

虽然在RFC3489RFC5389中的名称都是 STUN,但其全称是不同的。

在 RFC3489 里,STUN 的全称是 Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs), 即穿越 NAT 的简单 UDP 传输,是一个轻量级的协议,允许应用程序发现自己和公网之间的 NAT 类型,同时也能允许应用程序发现自己被 NAT 分配的公网 IP。这个协议在 2003 年 3 月被提出,目前已经被 STUN/RFC5389 所替代。

在 RFC5389 中,STUN 的全称变为 Session Traversal Utilities for NAT,即 NAT 环境下的会话传输工具,是一种处理 NAT 传输的协议,但主要作为一个工具来服务于其他协议。和 STUN/RFC3489 类似,可以被终端用来发现其公网 IP 和端口,同时可以检测端点间的连接性,也可以作为一种保活(keep-alive)协议来维持 NAT 的绑定。和 RFC3489 最大的不同点在于,STUN 本身不再是一个 完整的 NAT 传输解决方案,而是在 NAT 传输环境中作为一个辅助的解决方法,同时也增加了 TCP 的支持。RFC5389 废弃了 RFC3489(因此RFC3489通常称为 classic STUN),但依旧是后向兼容的。STUN 是一种 Client/Server 的协议,也是一种 Request/Response 的协议,默认端口号是 3478。

STUN 完整的定义参考:RFC5398

3.2 TURN

TURN 是 Traversal Using Relay NAT 的缩写,即使用中继穿透 NAT,STUN 的中继扩展。简单的说,TURN 与 STUN 的共同点都是通过修改应用层中的私网地址达到 NAT 穿透的效果,不同点是 TURN 是通过两方通讯的“中间人”方式实现穿透。

TURN 完整的定义参考:RFC5766

3.3 ICE

ICE 是 Interactive Connectivity Establishment 的缩写,即互动式连接建立,由 IETF 的 MMUSIC 工作组开发出来的,它所提供的是一种框架,使各种 NAT 穿透技术可以实现统一。

ICE 跟 STUN 和 TURN 不一样,ICE 不是一种协议,而是一个框架(Framework),它整合了 STUN 和 TURN。

ICE 完整的定义参考:RFC5245

参考:
P2P 技术详解(一):NAT 详解——详细原理、P2P 简介
P2P 技术详解(二):P2P 中的 NAT 穿越(打洞)方案详解
P2P 技术详解(三):P2P 技术之 STUN、TURN、ICE 详解