P2P技术初窥

时间过的很快离上次更新文章已经有了两年之久,为了共同学习共同进步宗旨,绕网络模块主题开展一次技术分享,(回顾之前同事讲了一些主题,HTTP/HTTPS、DNS解析/DNS优化、网络安全加密、TCP/UDP/SOCKET)具体看看网络所包含的模块吧。


网络.png

内容还真不少,这些东西大多都偏向底层基础,在实际开发中大多数都是由系统或者优秀的三方框架来实现。本着了解底层实现细节知识更能快速掌握上层技术,那么这次分享就围绕P2P来展开,作为移动端开发者也为后续理解WebRTC等技术积累一点知识。
1)P2P概述
2)P2P应用的场景
3)P2P简单原理
4)NAT概述
5)NAT实现方式
6)NAT类型
7)NAT类型探测
8)内网穿透

P2P概述

P2P应用在金融、视频通话、文件下载,流媒体点播/直播等场景都有广泛应用,日常中我们微信视频通话,使用迅雷下载文件,中间都使用到了p2p技术。
P2P,全称叫做“Peer-to-peer”对等互联网络技术(点对点网络技术),它让用户可以直接连接到其他用户的设备,进行数据的交换。
举个简单例子,比如你喜欢一个女孩子,但是你们互相不认识,幸运的是刚好有这么一个人,你和女孩都认识她。你按捺不住对女孩的想念,你找到这个人拿到了女孩的联系方式,然后迫不及待的给这个女孩发送一条消息,然后你就焦急等待女孩给你回复,女孩接收你得消息开心回复了你。你和女孩之间聊天就可以理解点对点的方式聊天。当然在这里你们是依靠中间人建立的联系,在P2P中建立点对点联系是依赖集中服务器。

P2P简单的原理
网络环境.png

我们大部分上网的设备都处于私网(局域网)环境内,内网客户端想要上网就需要经历网关转发访问数据。服务器返回数据是返回给网关,再由网关转发给客户端。为什么要设计成这样,出于两个原因的考虑,一是全球范围内上网的设备很多IP地址不够,二是对外隐藏客户端提高安全性(客户端只能向外访问,外边访问不到客户端),正因为网络环境的这种设计使得点对点通信变得尤为复杂。
我们知道私网地址是不可以连接外网,需要对外访问只能通过公网地址。客户端在上网时通过网关做了NAT(私网地址与公网地址映射,网关维护映射表,此时从网关出去的IP数据包源地址替换成了公网地址)从上图可知道网关的出接口是公网地址,公网地址是可以被其他设备访问到,那么网关可以访问服务器,服务器也可以访问网关,网关与网关也是可以互相访问。


p2p简单原理.png

那么客户端A要直接访问客户端B,就可以利用网关访问到。可以简单理解成网关A与网关B在通信。要想知道P2P的建立过程,就不得不了解NAT,包括怎样去实现内网穿透的。

NAT概述

在这里我觉得百度百科讲的比我清楚,技术这个东西自己知道与要讲出来甚至写出来其实还是很不一样的,https://baike.baidu.com/item/nat/320024?fr=aladdin如果你不想点开没关系,那下面也会做一些NAT简单引用

NAT技术诞生背景

要真正了解NAT就必须先了解IP地址的使用情况,私有 IP 地址是指内部网络或主机的IP 地址,公有IP 地址是指在因特网上全球地址。RFC 1918 为私有网络预留出了三个IP 地址块,如下:

A 类:10.0.0.0~10.255.255.255

B 类:172.16.0.0~172.31.255.255

C 类:192.168.0.0~192.168.255.255

上述三个范围内的地址不会在因特网上被分配,因此可以不必向ISP 或注册中心申请而在公司或企业内部自由使用。
随着接入Internet的计算机数量的不断猛增,IP地址资源也就愈加显得捉襟见肘。事实上,除了中国教育和科研计算机网(CERNET)外,一般用户几乎申请不到整段的C类IP地址。在其他ISP那里,即使是拥有几百台计算机的大型局域网用户,当他们申请IP地址时,所分配的地址也不过只有几个或十几个IP地址。显然,这样少的IP地址根本无法满足网络用户的需求,于是也就产生了NAT技术。

NAT解释

NAT(Network Address Translation),是指网络地址转换。当在专用网内部的一些主机本来已经分配到了本地IP地址(即仅在本专用网内使用的专用地址),但又想和因特网上的主机通信(并不需要加密)时,可使用NAT方法。
这种方法需要在专用网(私网IP)连接到因特网(公网IP)的路由器上安装NAT软件。装有NAT软件的路由器叫做NAT路由器,它至少有一个有效的外部全球IP地址(公网IP地址)。这样,所有使用本地地址(私网IP地址)的主机在和外界通信时,都要在NAT路由器上将其本地地址转换成全球IP地址,才能和因特网连接。
另外,这种通过使用少量的全球IP地址(公网IP地址)代表较多的私有IP地址的方式,将有助于减缓可用的IP地址空间的枯竭。在RFC 2663中有对NAT的说明。
百度百科讲的很专业,让大家更直观了解组网有必要提供一个图

园区组网.png
A园区下面所有能上网设备都分配了一个10.0.197.*不重复的私网IP地址,A园区内的每台设备访问外网资源都要通过网关NAT将内部的私网地址转成A园区的公网IP地址59.36.211.209进行对外访问,外部服务返回数据给网关,网关通过查找NAT地址映射,把数据准确发送到内网下具体上网的设备。这样起到多台设备共用一个公网地址上网,起到减缓IPV4地址枯竭进程,有效的隐藏公网下的上网设备。

NAT实现方式

实现NAT的方式有三种 静态转换Static Nat、动态转换Dynamic Nat和端口多路复用OverLoad。

静态转换Static Nat

静态转换分两种,一种是IP静态转换,另一种是端口的静态转化。
一、IP静态转换
IP静态转换是指将内部网络的私有IP地址转换为公有IP地址,IP地址对是一对一的,是一成不变的,某个私有IP地址只转换为某个公有IP地址。即一个公网地址只能映射一个私网地址,所有外界访问公网地址都会访问到这台固定的设备上,公网资源全部分配给这个唯一的设备。对于静态NAT并不能节约公网IP地址使用,因为一对一静态的缘故,因此外界可以访问进来,内部也可访问出去。当设备要对外提供固定的某个服务就可以使用静态NAT。
二、端口静态转换
一个IP地址可以有65536个端口,0~1024端口一般分给系统使用,端口静态转换是指1024~65536端口每个端口对应唯一的私网IP地址某个固定端口,端口对应的私网IP地址端口是一成不变的。当外界访问公网地址的某个端口通过网关对应的NAT端口映射表就可以找到具体某个设备某个端口,因此外界可以访问某台设备固定端口,端口静态转化确实能够节省公网IP地址的使用,但是由于端口受限内网是无法访问出去的(由于设备访问外界发送数据包源端口地址是随机生成,因此你不知道端口号是多少,只有当私网地址端口和公网地址端口映射上了才可以访问外界)

动态转换Dynamic Nat

动态IP转化是指内部网络私有IP地址转化为公有IP地址,公网IP地址来源是从IP池中获取到。内网某台设备要向外发起访问路由到网关,网关从IP池中去获取公网IP地址,若IP池中没有IP地址就等待其它设备释放公网IP,如果能取到公网IP地址,该公网的所有资源内网都可以使用,这样私网设备就可以访问外界,当访问结束会释放公网IP,因此弊端在某时刻某些设备可以上网某些设备不能上网。

端口多路复用OverLoad

上面讲到端口的静态转换(简单说端口关系是静态绑定的),端口多路复用公网端口和私网端口是临时映射关系。内网私网地址某个端口向外访问会映射公网地址某个空闲端口,当访问结束连接断开,私网地址端口映射的公网地址端口会被释放出来给内网任意设备映射临时关系。这样很大程度节约了IP地址使用,由于零时端口映射关系,只能内网放完外界,外界不能访问到内网设备,满足了大批量设备需要上网的需求,一般园区网,家庭网,公司网都是这种组网形式。

NAT类型

了解NAT的实现方式,我们就可以对NAT进行分类。在做内网穿透我们就要判断NAT的类型。
NAT分类.png

NAT类型可以分为对称NAT、完全锥形NAT、IP受限NAT、端口受限NAT
一、对称型NAT
内部私网地址访问外部不同的设备都会映射一个新的公网地址。(一台内网设备 对应一个公网地址 对应一台外网设备 产生一对一的关系)
二、完全锥形NAT
将来自内网私有IP地址同一个端口号映射到公网IP某个端口。任意外部IP地址与端口对其自己公网的IP这个映射后的端口访问,都将定位到内部私网地址端口。

例子来源网络
例如:
A:192.168.8.100 ——NAT:1.2.3.4 ——C:292.88.88.88
[ok] C(292.88.88.88:2000) ——> NAT(1.2.3.4 : 8000) ——> A(192.168.8.100:5000)
[ok] C(292.88.88.88:3000) ——> NAT(1.2.3.4 : 8000) ——> A(192.168.8.100:5000)
[ok] D(292.99.99.99:3000) ——> NAT(1.2.3.4 : 8000) ——> A(192.168.8.100:5000)
任何发送到 NAT(202.100.100.100:8000) 的数据都可以到达 A(192.168.8.100:5000)

三、IP地址受限锥形NAT
IP地址受限锥形NAT大致可以理解在完全锥形NAT加上了IP访问限制,并不是所有外部设备都可以访问到内网设备,只有通过内网设备对某个外部设备主动发起过连接,然后这个外部设备就可以访问到内网这个设备,但端口不做限制。

例子来源网络
例如:
A:192.168.8.100 ——NAT:1.2.3.4 ——C:292.88.88.88
//可以建立通信
[ok] C(292.88.88.88:2000) ——> NAT(1.2.3.4 : 8000) ——> A(192.168.8.100:5000)
[ok] C(292.88.88.88:3000) ——> NAT(1.2.3.4 : 8000) ——> A(192.168.8.100:5000)
//不能建立通信 如果要建立通信 必须由内网设备发送数据包到 292.99.99.99:3000 建立连接后
[no] D(292.99.99.99:3000) ——> NAT(1.2.3.4 : 8000) ——> A(192.168.8.100:5000)
任何从C发送到 NAT(1.2.3.4:8000)的数据都可以到达A(192.168.8.100:5000)

四、端口受限锥形NAT
端口受限锥形NAT它比IP地址受限锥形NAT受限更为严格,能接受到外界的数据报范围更加小了,除了IP受限外还添加了端口受限。内网设备只允许自己外网建立连接的地址端口给自己发送数据报

例子来源网络
例如:
A:192.168.8.100 ——NAT:1.2.3.4 ——C:292.88.88.88
//可以建立通信
[ok] C(292.88.88.88:2000) ——> NAT(1.2.3.4 : 8000) ——> A(192.168.8.100:5000)
//不能建立通信   必须由内网设备发送数据包到 292.88.88.88:3000 建立连接后
[no] C(292.88.88.88:3000) ——> NAT(1.2.3.4 : 8000) ——> A(192.168.8.100:5000)
C(202.88.88.88:2000)发送到 NAT(1.2.3.4:8000)的数据都可以到达A(192.168.8.100:5000)
NAT类型探测与内网穿透

对于NAT类型探测与内网穿透详细过程可以看 http://www.52im.net/thread-2872-1-1.htm
在实际的网络情况中,我们上网的设备所处的网络环境不同。处在NAT网下的设备要进行点对点的通信,首先判断出设备各自所处的网络NAT类型。然后才能根据NAT的类型实现相应的UDP/TCP打洞。
关于内网穿透建立点对点的连接,已经有了下面一些成熟的方法。STUN(Session Traversal Utilities for NAT,NAT会话穿越应用程序)技术就是其中比较重要的一种解决方法,并得到了广泛的应用。除此之外,还有UPNP技术,ICE交互式连接建立,TURN中继NAT穿越技术等。
打洞技术是通过中间服务器的协助在各自的NAT网关上建立相关的表项,使P2P连接的双方发送的报文能够直接穿透对方的NAT网关,从而实现P2P客户端互连。如果两台位于NAT设备后面的P2P客户端希望在自己的NAT网关上打个洞,那么他们需要一个协助者——集中服务器,并且还需要一种用于打洞的Session建立机制。
重点介绍一下 客户端怎么通过STUN(NAT回话穿越应用程序的原理)探测出自己的公网地址与NAT的内型。STUN协议 利用STUN客户端与STUN服务器(集中服务器)通信(利用上面所讲到NAT类型通信特点来判断设备的具体所处的什么NAT网络下)
一、NAT类型探测
文字描述不如上图来的直接

NAT类型探测.png

二、NAT穿越方法
1)打洞技术(Hole Punching)
介绍一下打洞原理:位于NAT后的内网设备节点需要向外发送数据包,通过NAT建立起内网IP地址端口和公网IP地址端口的映射关系。然后通过某种方式将映射后的外网地址和端口通知给对端节点设备。最后对端设备收到内网设备NAT后的公网地址端口,并向改公网地址端口发送数据包,然后该数据包就会被NAT转发给内网设备。
在这里提出两个问题,怎么将自己公网地址通知个对端?对端知道自己的公网地址端口就一定能建立通信?
建立点对点通信.png

客户端通过STUN服务器获取到自己的公网地址端口NAT类型,再将自己身的信息注册到中继服务器,客户端1向中继服务器发起获取客户端2信息的请求,获取到客户端2的信息向客户端 2网关发起直连,获取对端公网地址已经解决了。怎么知道能否建立点对点的通信,其实上面已经讨论到了,STUN服务器探测到客户端各自的NAT类型,具体使用什么穿越方法参照下表(下图源于网络若侵权请联系删除)

对应NAT类型穿越方法表.png

感兴趣的可以自己去分析一下建立点对点通信的步骤。具体的打洞过程包括Relay(服务器中转)技术可以去看看http://www.52im.net/thread-2872-1-1.htm接下来挑几个例子来看看具体的打洞过程。
例子1:
客户端1 主动连接 客户端2 客户端1处于任意NAT类型环境 客户端2处于IP受限NAT型环境,客户端都获取到了对端信息情况下。
任意型NAT-IP受限型NAT穿透过程.png

例子2:客户端1处于任意NAT类型(除对称NAT外)环境 客户端2处于端口受限NAT型
任意型NAT-端口受限型NAT穿透过程.png

最后介绍一下端口预测:
端口预测,就是统计客户端多次连接的地址,总结出客户端外网端口变化的规律,然后把预测出的下一个端口和外网地址发给对方,然后促成双方通信。这个方法穿透成功率极低。一般P2P项目再建立点对点连接失败后都会利用服务器来进行数据转发。

参考文献

https://baike.baidu.com/item/nat/320024?fr=aladdin
http://www.52im.net/thread-2872-1-1.html
https://blog.csdn.net/WangZekun_wolf/article/details/89102996

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容