0%

p2p打洞技术研究

p2p技术简介

对等式网络(peer-to-peer,简称P2P),又称点对点技术,是无中心服务器、依靠用户群(peers)交换信息的互联网体系。它的作用在于,网络的参与者共享他们所拥有的一部分硬件资源(处理能力、存储能力、网络连接能力、打印机等),这些共享资源通过网络提供服务和内容,能被其它对等节点(Peer)直接访问而无需经过中间实体,减低以往网路传输中的节点,以降低资料遗失的风险。与有中心服务器的中央网络系统不同,对等网络中的每个用户端既是资源(服务和内容)提供者(Server),又是资源获取者(Client),任何一个节点无法直接找到其他节点,必须依靠其用户群进行信息交流。

p2p网络拓扑图(讲一些废话)

如图,我们可以总结出P2P网络的一些特征:

  • 非中心化: P2P是全分布式系统,网络中的资源和服务分散在所有的节点上,信息的传输和服务的实现都直接在节点之间进行,可以无需中间环节和服务器介入。
    可扩展性:用户可以随时加入该网络,系统的资源和服务能力随之同步扩充。理论上其可扩展性几乎可以认为是无限的。
  • 健壮性: 因为服务是分散在各个节点之间的,部分节点或网络遭到破坏对其他部分的影响很小,故P2P具有耐攻击、高容错的特点。P2P网络一般在部分结点失效时能够自动调整整体拓扑,保持其它结点的连通性。P2P网络通常都是以自组织的方式建立起来的,并允许结点自由地加入和离开。
  • 高性价比: P2P架构可以有效地利用互联网中散布的大量普通结点,将计算任务或存储资料分布到所有结点上。利用其中闲置的计算能力或存储空间,达到高性能计算和海量存储的目的。
  • 隐私保护: 在P2P网络中,由于信息的传输分散在各节点之间进行而无需经过某个集中环节,用户的隐私信息被窃听和泄漏的可能性大大缩小。
  • 负载均衡: 由于每个节点既是服务器又是客户端,减少了传统C/S模型中对服务器计算能力、存储的要求,同时因为资源分布在多个节点,更好的实现了整个网络的负载均衡。

关键技术

分包发送

由于p2p是点到点的连接,文件从多个的节点上获取,就需要将文件进行分块处理。这一部分主要是文件的分包、排序、校验和合并的过程,不是很难的技术。

文件下载技术

种子文件信息

拿bittorrent距离,种子文件储存的信息有

1
2
3
4
5
- info:存储资源文件的元信息
- piece length
- pieces
- name/path
- announce:描述tracker服务器的URL
  • info:info键对应的值又是一个字典结构,BT协议将一个文件分成若干块,便于客户端从各个主机下载各个块。其中的piece length键值对表示一个块的长度,通畅情况下是2的n次方,根据文件大小有所权衡,通长越大的文件piece length越大以减少piece的数量,降低piece数量一方面降低了种子文件保存块信息数目的大小,一方面也减少了下载时需要对块做的确认操作,加快下载速度。目前块的大小通常是256KB,512KB或者1MB。

  • pieces:表示每个块的正确性验证信息,每一块均对应一个唯一的SHA1散列值。该键对应的值是所有块的SHA1散列值(每个块所对应的散列值大小为20字节)连接而成的字符串。

  • name/path:表示具体文件的信息。因为BitTorrent协议允许将数个文件和文件夹作为一个BT下载进行发布,因此下载方可以根据需要勾选某一些下载文件。注意,这里将数个文件也砍成一个数据流,因此一个piece如果在文件边界上,可能包含不同文件的信息。

  • announce:保存的是tracker服务器的URL,在一些扩展协议中,announce可以保存多个tracker服务器作为备选。

tracker服务器

一般p2p连接下载文件需要有一个公网下的tracker服务器帮助获得各个节点的信息,服务器上面保存了各个文件的节点列表。节点列表中的各个节点可以随时加入和退出,列表中一般储存的是

  • 文件的编码值
  • 节点名称
  • ip
  • port

当一个节点想要下载某个文件,向tracker服务器上请求节点列表,然后连接各个节点进行下载传输。

内网穿透

到这里是大多数网上讲解p2p的内容,但有一个关键的技术没有说明,就是内网穿透。

节点通常是各个用户的电脑,所处环境一般为局域网内。总所周知局域网的路由器维护一个nat列表,会将不请自来的消息过滤掉,也保证了网络的安全性。但对于p2p来说就比较麻烦,无法让两个局域网内的节点相互建立连接进行文件传输。这里讲两个重要的内网穿透技术:UDP打洞和TCP打洞

打洞之前需要了解一下路由器的nat类型,部分nat类型不支持打洞。

NAT类型

  1. 全克隆(Full Cone): NAT把所有来自相同内部IP地址和端口的请求映射到相同的外部IP地址和端口。任何一个外部主机均可通过该映射发送IP包到该内部主机。
  2. 限制性克隆(Restricted Cone): NAT把所有来自相同内部IP地址和端口的请求映射到相同的外部IP地址和端口。但是,只有当内部主机先给IP地址为X的外部主机发送IP包,该外部主机才能向该内部主机发送IP包。
  3. 端口限制性克隆(Port Restricted Cone): 端口限制性克隆与限制性克隆类似,只是多了端口号的限制,即只有内部主机先向IP地址为X,端口号为P的外部主机发送1个IP包,该外部主机才能够把源端口号为P的IP包发送给该内部主机。
  4. 对称式NAT(Symmetric NAT): 这种类型的NAT与上述3种类型的不同,在于当同一内部主机使用相同的端口与不同地址的外部主机进行通信时, NAT对该内部主机的映射会有所不同。对称式NAT不保证所有会话中的私有地址和公开IP之间绑定的一致性。相反,它为每个新的会话分配一个新的端口号。
  • 第一种最为理想,基本就是无需打洞;
  • 第四种最糟糕,根本就不能打洞。好消息就是这种nat基本没有,很少。
  • 所以关键是第二和第三种nat类型。

UDP打洞

先讲UDP打洞主要是因为UDP打洞要比TCP打洞方便的多,而且UDP传输的速度也要比TCP快很多。

UDP打洞主要是建立两边路由器NAT的规则,分为以下几步进行:

  1. 两个节点A、B都向公网内的tracker服务器C发送数据,两边的NAT-A和NAT-B就有了一条规则$A \Leftrightarrow C$和$B \Leftrightarrow C$,允许A和B接收来自C的数据。
  2. 服务器C获得了A和B在公网映射的ip和端口,交叉发送给对方。
  3. 关键点 A向B在公网映射的ip和端口发送一条数据,会被NAT-B拦截过滤掉,因为没有这条NAT规则。但是NAT-A中多了一条规则$A \Leftrightarrow B$。
  4. 这时候B向A发送一条数据就可以畅通无阻地通过NAT-A到达A。这时NAT-B也有了一条规则$B \Leftrightarrow A$。到这里A和B就可以进行UDP通信了。

这一步已经通过两台电脑加上两个虚拟机验证过了,方案可行。

TCP打洞

TCP打洞和UDP打洞的原理类似,但是由于

  • TCP连接需要三次握手
  • TCP client占用一个端口只能连接一个服务器
  • TCP server可以连接多个TCP client

这里就有些麻烦,分为以下几步进行:

  1. 两个节点A、B都和公网内的tracker服务器C的主连接端口进行TCP连接,服务器C获得了A和B在公网映射的ip和端口,这个连接不会断掉,通过这个连接也可以维护节点列表。
  2. A使用另外的端口(打洞端口)连接服务器C的协助打洞端口,服务器获取到A打洞的ip加端口,同时在该端口号上启动侦听(如果是NAT类型1可能直接就连接成功)。注意由于要在相同的网络终端上绑定到不同的套接字上,所以必须为这些套接字设置SO_REUSEADDR属性(即允许重用),否则侦听会失败。
  3. B也连接服务器C的协助打洞端口,但连接后立刻断开,并启用监听。这时候C获取到B的公网ip和端口。
  4. C通过主连接端口告诉B:A打洞的公网ip和端口。
  5. B向A发起TCP连接请求(如果为NAT类型1,这一步就已经可以建立连接),被NAT-A过滤掉,但是NAT-B添加规则$B \Leftrightarrow A$
  6. B通过主连接端口告诉C:我已经准备好了。
  7. C通过主连接端口告诉A:B打洞的公网ip和端口。
  8. A向B发起TCP连接,到此连接成功,NAT-A也添加规则$A \Leftrightarrow B$。

这一步由于需要进行网络编程进行验证,代码没来得及写完,没来得及验证。