<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont

  1. 云栖社区>
  2. 博客>
  3. 正文

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont

神棍先生 浏览435
展开阅读全文

大 概在一年前我就研究过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内网穿透)。 先上一张图(自己画的,画得不好看见谅啊)

[转]  P2P内网穿透原理 - 小伙 - 革命尚未完成,哥还需继续努力!
  
箭头代码通讯的意思,还有就是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.发送数据包的顺序容易乱序
           关于第一个问题,我们可以对发包做个丢包重发机制。第二个问题,只需在发送的数据包头做个标记即可。

 

好了下面我们讨论TCP协议的P2P技术,TCP协议的通讯不存在UDP协议的两个问题,当然也有它的缺点,就是对网络的开销比较大。


           虽然TCP协议的P2P技术在网络上的资料不太多,但其实TCP协议的内网打洞和UDP也差不多,只是有少许不同,这里我简单做下介绍。(TCP协议的内网打洞我现在还是写不出来,只是有一个问题没有解决,就是端口重用问题,希望大牛可以给我指点一下



           和上面的图一样,我们要实现主机1和主机2直接的TCP协议的P2P通讯。下面的步骤资料来自于网络(略有删改)

           主机1和主机2 进行通讯的步骤
           1.服务器启动两个网络侦听,一个叫【主连接】侦听,一个叫【协助打洞】的侦听。 
           2. 主机1和主机2 分别与服务器的【主连接】保持联系。
           3.当 主机1需要和主机2 建立P2P的TCP 连接时,首先连接服务器的【协助打洞】端口(此时NAT1已经自动打了一个“洞”),并发送协助连接申请。同时在本机连接到服务器【协助打洞】端口的端口 号上启动侦听。注意由于要在相同的网络终端 上绑定到不同的套接字上,所以必须为这些套接字设置 SO_REUSEADDR 属性(即 允许重用),否则侦听会失败。
            4. 服务器的【协助打洞】连接收到主机1 的申请后通过【主连接】通知主机2,并将主机1 经过 NAT1 转换后的公网 IP 地址和端口等信息告诉主机2。
            5.主机2收到服务器 的连接通知后首先与服务器的【协助打洞】端口连接(此时NAT2已经自动打了一个“洞”),随便发送一些数 据后立即断开,这样做的目的是让服务器能知道主机2 经过 NAT2 转换后的公网 IP 和端 口号。
            6.主 机2尝试与主机1的经过 NAT1转换后的公网 IP 地址和端口进行 connect,根据不 同的路由器会有不同的结果,有些路由器在这个操作就能建立连接,大多数路由器对于不请自到的 SYN 请求包直接丢弃而导致 connect 失败,但 NAT1会纪录此次连接的源地址和端口号,为接下来真正的连接做好了准备,下次主机1 就能直接连接到主机2刚才使用的端口号了。
            7.主机2打洞的同时在相同的端口上启动侦听。主机2 在一切准备就绪以后通过 与服务器的【主连接】回复消息“我已经准备好”,服务器在收到以后将主机2 经过 NAT2 转 换后的公网 IP 和端口号告诉给主机1
            8. 主 机1 收到 服务器回复的主机2 的公网 IP 和端口号等信息以后,开始连接到 主机2 公网 IP 和 端口号,由于在步骤 6 中 主机2 曾经尝试连接过 A 的公网 IP 地址和端口,NAT1 纪录 了此次连接的信息,所以当 主机1 主动连接 主机2 时,NAT2 会认为是合法的 SYN 数 据,并允许通过,从而直接的 TCP 连接建立起来了。


            有的人会问,为什么主机1和主机2不用发送数据到服务器上来维持NAT1和NAT2的“洞”呢? 这就是TCP“打洞”与UDP“打洞”的不同了,TCP打洞的“洞”是没有生命周期的,等到连接断开,TCP的“洞”就会自动关闭。




        注意以上的TCP穿透步骤没有经过我的测试,所以不知道其可行性,请大家自行测试(网络中对于TCP内网穿透技术也存在各种质疑,所以其可行性尚还不知道)

,但个人觉得原理应该没错的

              另外说下基于P2P技术的升级P4P技术,百度百科:http://baike.baidu.com/view/595104.htm,能看明白P2P技术的,看这个应该也不成问题(P4P技术主要用于传输与共享文件)

网友评论

登录后评论
0/500
评论
神棍先生
+ 关注