p2p之NAT穿透

什么是NAT

NAT(Network Address Translation),网络地址转换。是1994年提出的。当在专用网内部的一些主机本来已经分配到了本地IP地址(即仅在本专用网内使用的专用地址),但现在又想和因特网上的主机通信(并不需要加密)时,可使用NAT方法。
。装有NAT软件的路由器叫做NAT路由器,它至少有一个有效的外部全球IP地址。这样,所有使用本地地址的主机在和外界通信时,都要在NAT路由器上将其本地地址转换成全球IP地址,才能和因特网连接。
同样还有NAPT,网络地址、端口转换。现在一般穿透规则就是通过获取ip、端口来实现的,重点是实现穿透,所以以下统称NAT即可。

为什么要穿透NAT

NAT可以有效的减缓全球IP枯竭的问题。但是同时NAT也屏蔽了内部设备。

比如在局域网A下有一个内网IP地址为192.168.1.155的设备A,现在一个设备B想要访问这个设备A,根据设备B所在网络可分为一下情况。

  • 设备B同在局域网A中:
    设备B可直接通过设备内网ip 192.168.1.155 地址访问设备A;
  • 设备B在外网:
    设备B无法通过设备A内网访问设备A;
  • 设备B在不同局域网A的局域网B中:
    设备B在通过ip 192.168.1.155 访问的时候可能访问到局域网B下内网IP也为192.168.1.155的设备C,也可能找不到该ip,但是无法访问设备A。

这就是为什么在内网建立一个tcp或者udp服务,内网客户端可以通过ip和端口号直接通信,而外网却无法访问该内网建立的服务。
要实现p2p(Peer to Peer),首先我们的要知道客户端ip和端口号,但是通过局域网路由器的NAT转换,生成的外网ip和端口我们无法预知,这样我们就无法建立p2p连接。

NAPT转换

如果你还是不明白NAT为什么屏蔽了内部设备,接下来举个NAT转换例子就明白了。
例:
内网机器A ip(192.168.1.188) 端口(9999) - 访问外网目标主机B ip(220.233.28.42) 端口(8888):

1.数据包

目的主机:220.233.28.42
目的端口:8888

源主机:192.168.1.188
源端口:9999 (用户自定义或随机)

2.地址转换

目的主机:220.233.28.42
目的端口:8888

源主机:123.206.41.242 (NAPT转换,为路由器外网ip)
源端口:17309 (NAPT转换)

3.记录地址映射

192.168.1.188:9999 ---- 123.206.41.242:17309

4.外网主机B向内网主机A返回响应消息

目的主机:123.206.41.242
目的端口:17309

源主机:220.233.28.42
源端口:8888

5.NAPT查找地址映像并转换

目的主机:192.168.1.188
目的端口:9999

源主机:220.233.28.42
源端口:8888

通过地址转换,主机A的内网地址被映射之后我们是无法预知的,而且我们无法通过主机A的内网地址直接访问A,所以NAT屏蔽了主机A。

通过例子可以看到,当主机A访问外网主机B时,通过NAT随机分配一个(外网ip为路由器外网ip)端口,这样就把内网地址映射成了一个唯一的外网地址。然后外网主机B响应主机A时,主机B不直接访问主机A,而是通过NAT转换后的地址访问路由器,路由器就会通过映射把数据分配给内网主机A。这也就是NAT穿透的原理。

NAPT穿透原理

通过双方所在网络环境不同可分为一下模式:

  • 一个在局域网,另一个在外网
  • 都在不同的局域网
  • 都在相同的局域网

上一章节已经提到了一种穿透方式,即:局域网-外网的访问模式,因为主机B在外网,ip端口确定,主机A可以直接通过B的外网地址访问B,外网主机B首先接受到了主机A的数据包,便可以知道主机A经过NAT转化后的外网地址,然后就可以进行相互通信。
但是如果双方都在不同的局域网,互相都不知道自己的外网地址怎么办。
这种情况就需要利用一个拥有唯一IP的中间服务器S,因为S ip固定并且已知,就让两个设备都向S发送数据包,S就可以的知道两个设备的公网ip,在设备p2p通信之前先去服务器查找对方的ip、端口,就可以实现通信。
两个设备同时处在同一个局域网下,可以不通过NAT,直接用内网ip进行通信,这是最节省带宽的方式。当然,也可以通过第二种,通过S服务器来得到外网ip端口,这种情况外网的IP是相同的(同一个路由器),只是分配的端口不同。

发送数据的方式利用UDP,虽然UDP不可靠,但是UDP可以轻松实现穿透。通过浏览各大博客,都没有找到通过TCP实现穿透的项目,甚至有人说TCP几乎不可能实现穿透(博主初学,还望指点)。

使用过UDP的肯定知道,首先创建一个UDP监听端口,然后可以通过这个端口发送和接收数据包。NAT会把这个监听端口映射为外网ip和端口。我们只需要通过端口发送数据包给服务器就可以让服务器拿到这个端口信息,然后可以让其他客户机通过这个端口的信息来发送数据给该端口。

在这里NAPT对UDP的端口映射(session)还有一定的规则:

  • A.源地址(内网ip)不相同,忽略其他因素,则session不同。
  • B.源地址相同,源端口不同,忽略其他因素,则session不同。
  • C.源地址相同,源端口相同,目标地址不同,对于不同的NAPT,session可能不同。(一般大部分是相同的,不同的无法进行穿透)
  • D.源地址相同,源端口相同,目标地址相同,任何端口,session一定相同。

session并不是长期存在的,不同的路由器session储存时间不同,短的有的几十秒,长的可能有的几分种。要想维持这个session可以通过心跳包来维持,比如10秒向服务器发送一个心跳包。并且对于上面第三种情况,如果最后session不同,就无法实现穿透(这种类型一般少见)。

NAT穿透UDP具体实现

本来是打算把我的java代码黏贴出来的,后来想了想,我写的只是其中一种实现方式,不同语言也有不同的实现方式,我就来说说实现的步骤,就不再写代码了。也挺简单的。

  1. 客户端建立一个UDP监听端口
  2. 客户端做一个心跳包向服务器发送数据包
  3. 服务器接收到心跳包后,储存客户端的ip、端口信息

当客户端要进行p2p通信的时候

  1. 发送方服务器查询接收方ip、端口
  2. 数据包定向ip、端口发送数据包
  3. 完成通信

注意 重点

到此,你以为结束了? 那就大错特错了。
到这里你会发现,接收方(以下统称A)可能拿不到数据包,这种情况出现在接收方在局域网内(需要穿透NAT)。
前面讲的,并不是仅仅获取到设备外网地址就可以成功穿透,还要注意NAT会把不认识的数据丢弃。
这是为什么?
NAT丢弃了你这个来源不明的包,根本没有分发给接收设备A。
为什么叫来源不明呢,这是因为首先A的UDP端口给服务器发数据包,A的NAT创建了一个session,这样A再接收到服务器的数据时,会查找这个映射(A<--->服务器),这个映射就储存在这个session里。但是发送方(B)向A的NAT发送数据(这是在B的NAT建立对A的映射),没有指向B的映射,所以数据包被A的NAT丢弃。
那怎么解决呢,其实让A也向B发一个数据包就好了,这样A的NAT会建立一个对B的session,这样再收到B的数据NAT就可以查找到对应的映射了。

之前提到的NAPT对UDP的session映射,源地址相同,源端口相同,目标地址不同,对于不同的NAPT,session可能不同。这条规则是依据不同的NAT的。Symmetric NAPT会导致session不同,Cone NAPT则是相同的。对于p2p只要一方使用的是Symmetric NAPT就会导致无法穿透。具体可自行百度。

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

推荐阅读更多精彩内容