P2P内网穿透原理

 大概在一年前我就研究过P2P技术,但始终攻不破NAT内网穿透这个难题(因为本人小菜,对于网上说的一些原理始终没看明白),所以也渐渐开始淡忘这门技术了。(用了P2P技术,就可以实现无需路由的端口映射内网与内网或内网于外网直接的通讯,记得在邪八的一位大牛在谈下一代木马问题的时候就说过:下一代的木马应该用P2P技术在网络组建巨大的P2P网络,而控制端就隐藏在这巨大的P2P网络中,大大提高控制端在网络中的隐身程度)
         前几天我突然对P2P技术又产生了浓厚的兴趣(也不记得是出于什么原因了),并且研究了一个下午之后终于弄清楚它的原理并用了半天时间写了一个简易的基于P2P协议的聊天工具,具体源码我会在“编程技术”这个板块发布。

         注意,文章比较长,想掌握P2P技术的请认真看完,好好理解,不懂的可以回帖提问,我会尽我能力进行解答!因为本猪能力有限,文章出现的错误还请大牛们不吝改正。
         PS:红色的文字代表重点蓝色的表示次重点


         首先先了解一下P2P技术,下面的文章源于百度(增加了个人的说明)。

         点对点技术(peer-to-peer, 简称P2P)又称对等互联网络技术,是一种网络新技术,依赖网络中参与者的计算能力和带宽,而不是把依赖都聚集在较少的几台服务器上(这种技术可以大大减轻服务器的负担)。P2P网络通常用于通过Ad Hoc连接来连接节点(从而实现了节点之间的通讯)。这类网络可以用于多种用途,各种档案分享软件已经得到了广泛的使用(QQ聊天、迅雷、大部分网络播放器都使用了该技术)。    其他介绍请看:http://baike.baidu.com/view/21058.htm     还有关于NAT的介绍的百科:http://baike.baidu.com/view/16102.htm  (有兴趣了解的可以去看看,不看也行,这篇文章里我会进行部分介绍)


         其实P2P技术并不难,关键了理解了其中的原理,实现了NAT内网穿透,那么就可以轻松写出一个基于P2P协议的软件。
         另外需要说下的就是:P2P技术也有基于UDP协议和TCP协议之分,下面我先介绍UDP协议(重点都是在于NAT内网穿透)。 先上一张图(自己画的,画得不好看见谅啊)

箭头代码通讯的意思,还有就是NAT外面就属于外网,里面就是内网。(这张图属于杂P2P或混合P2P)
希望大家可以通过这张图以及我的文章来掌握P2P技术,我也会在排版方面下点功夫。(网络上已经有很多关于P2P技术的文章了,但我觉得那些说得都比较深,对于像我这样的小菜来说掌握起来是有难度的,所以我尽量说简单点,如果掌握之后想深入了解,可以在网上找相关的文章)


          正常情况下,主机1想向主机2发送数据:从主机1开始——到NAT1——到外网——到NAT2到了NAT2这里,主机1向主机2发送的数据就会丢弃了,为什么呢?NAT2在此时相当于一个防火墙,为了安全,对于主机1发送过来的数据会做丢弃处理。  
          这时候主机1想要和主机2通讯有两种方法: 
         1. 在路由上做端口映射,把通讯需要的端口映射到主机2(这个对于在内网玩过远控的人都知道吧)
         2. 在NAT2处进行“打洞”,意思把通讯需要的端口在NAT上标记出来,让NAT知道访问这个端口就是要访问主机2(这个和端口映射的意思差不多)

         方法1相信大家都知道吧,我们来讨论方法2来实现P2P通讯。
         我们如何在NAT上进行“打洞”呢?上面我已经说过,为了安全,NAT2会把主机1发来的数据丢弃,所以我们打洞只能在主机2上进行操作!(其实UDP协议的NAT打洞挺简单的哦)

         要在NAT上打洞,也要先了解下NAT在通讯方面的作用。
         不知大家有没有注意到,例如我在本机开了一个1080这个端口连接别人的电脑,那么在别人电脑上用端口查看的工具看到本机的端口就不是1080了,而是其他的端口号(比如是:5000吧)。
         为什么会出现这种情况呢?这是NAT经过端口转换后的一个结果,此时NAT上就会把外网访问5000这个端口看做是访问本机的1080这个端口了,这也就是我们所说的“打洞”。

          我们回到刚才的那张图上。(注意我们现在讨论的是UDP协议的NAT内网打洞
          主机1想访问主机2,那么总要知道主机2的外网IP吧。所以我们架一个服务器作为存储主机IP的工作。

          那么我说下主机1和主机2 进行P2P通讯的步骤
          1.主机1和主机2首次发送数据到服务器(当发送第一次数据的时候,NAT上就会自动打了一个“洞”,服务器此时就把它们的外网IP和经过NAT端口转换的端口存储起来)。
          2.数秒发送一次数据到服务器,就当作是心跳包(因为UDP协议的内网打洞在NAT上的端口有生命期,一段时间没有数据通过NAT上的“洞”这个“洞”就会自动关闭)
          3.当主机1要访问主机2的时候,主机1先向服务器发送信息要求获取主机2的外网IP和经过NAT2端口转换的端口
          4.因为在第2步的时候,NAT1和NAT2已经打好洞了,所以此时就不用再考虑其他,直接向主机2的外网IP加经过NAT2端口转换的端口发送数据就行了(格式是“主机2外网IP”+“:”+“NAT2转换的端口”),如无防火墙的拦截,主机2就可以收到主机1发送的数据了。

经过这四步,主机1和主机2就可以通讯了,相反,主机2想要向主机1发送数据,只需要把上面步骤的主机1与主机2的位置调转即可。相信大家经过上面的理解之后都能知道NAT打洞是怎么回事了吧。
           还需注意的就是UDP协议通讯存在两个问题,1.容易丢包  2.发送数据包的顺序容易乱序
           关于第一个问题,我们可以对发包做个丢包重发机制。第二个问题,只需在发送的数据包头做个标记即可。
posted @ 2016-05-23 16:04  清澈见底  阅读(1278)  评论(0编辑  收藏  举报