P2P原理

关键字

stun协议\P2P\UDP打洞\NAT

常用方法

中继

使用中继服务器连接两台内网设备,受限于中继节点性能。

逆向连接

当客户端A、B之一有公网地址时可以使用该方法。

UDP打洞

最常见的方法

利用锥形NAT(下文将介绍NAT分类)会将 内网ip+端口 绑定一个 外网ip+端口 的特性实现。理论上来说,利用该特性就可以实现任意主机间的通信,但往往NAT会做很多限制,导致这种直接通信无法完成。下面以限制最多的 Restricted-Port NAT 为例说明:

网络拓扑图

Client A和B仅具有内网地址,有Restricted-Port NAT功能的router A和B将他们的内网地址及端口和外网地址及端口进行绑定,Server S具有外网地址。

限制前提

Restricted-Port NAT 会直接丢弃其他主机 主动 发送过来的报文,只有它向另一台主机发送一个报文后,它才会接收该主机发送过来的一个报文。所以即使A和B映射了公网地址也不能直接通信。

打洞过程
  1. Client A和B分别向S发送一条报文,S会记录下A和B的出口地址及端口(即:1.1.1.1:7777和2.2.2.2:8888)
  2. S分别向A和B返回对方的出口地址及端口
  3. A和B分别向对方的出口地址发送一个报文,由于Restricted-Port NAT的限制,该报文均会被丢弃。但同时,由于都向对方发送了报文,后面就能接收对方发送的报文。此时A和B就可以P2P通信了

NAT分类

基础NAT

只有主机本身就具有公网IP的情况下才能使用,此时基础NAT中会记录一张内网ip和公网ip的映射表

内网地址外网地址
192.168.1.1111.1.1.1
192.168.1.2222.2.2.2
192.168.1.3333.3.3.3

NAPT

允许多个内网主机公用一个公网IP,通过端口区分,此时NAT中会记录如下映射(有时间限制,超时删除)

内网地址外网地址
192.168.1.111:11111.1.1.1:1111
192.168.1.222:11111.1.1.1:2222
192.168.1.333:55551.1.1.1:3333
完全锥型

内网地址+端口 和 外网地址+端口 一一绑定,不因访问资源地址变化而变化

出口地址可自由接收 任意外部主机的任意端口 发送来的报文

受限锥型

内网地址+端口 和 外网地址+端口 一一绑定,不因访问资源地址变化而变化

只有通过出口地址向另一台主机发送一个报文之后,才能接收该主机 任意端口 发送过来的报文。该主机直接发送的报文将被丢弃

端口受限锥型

内网地址+端口 和 外网地址+端口 一一绑定,不因访问资源地址变化而变化

只有通过出口地址向另一台主机 指定端口 发送一个报文之后,才能接收该主机 指定端口 发送过来的报文。该主机其他端口或其他主机发送的报文将被丢弃

对称型

需要访问的目标主机或端口不同,就会为该内网主机分配不同的外网ip+端口映射。这种类型的NAT很难进行p2p通信

NAT类型检测

如何知道内网设备使用的是哪一种NAT。

前提

两台具有公网ip的主机 S1和S2,一台处于内网的主机 Client,但不知道它的出口NAT类型

检测操作

  1. client向S1发送一个报文,S1收到报文后记录该报文的出口IP+端口并返回给client,client将S1返回的地址和自己本身的地址(例如使用ip addr命令获取)进行比较,如果相同,则client本身就使用的是公网地址,即NAT类型为 基础NAT
  2. client向S1和S2同时发送一个报文,S1和S2均返回其收到的报文出口地址,client对比它们返回的地址,如果不同,则使用的是 对称型NAT
  3. client向S2发送一个报文,S2将报文出口地址发送给S1,S1向该地址发送UDP报文,若client可以收到该报文,则使用的是 完全锥型NAT
  4. client向S1发送一个报文,S1获取到报文出口地址后,使用另一个端口向该地址发送一个报文,若client收到该报文,则使用的是 受限锥型NAT
  5. 其他则使用的是 端口受限NAT

Leave a Comment