当前位置: 首页 >> 网络协议与安全 >> P2P穿透UDP/TCP原理
 

P2P穿透UDP/TCP原理

作者:      来源:zz     发表时间:2007-01-18     浏览次数:      字号:    

 
5.5 情况2<可预测的,可预测的,no LSR>
A  X  B
|-------2a----->|<------2b------|
|-------3a----->|<------3b------|
|<------4a------|-------4b----->|
|-------5b------|-------------->|
|<--------------|-------5a------|
|-------6a----->|<------6b------|
 
3:情况2
   
情况1依靠于可用的松散源路由。许多路由器目前设置了预防松散源路由,同时将具有代表性地抛弃请求服务的包。同样地,依靠于松散源路由的技术在实际中将有很高的概率会失败。如果松散源路由不可利用,SYN序列号可以利用一个外出通道(他们预先连接到X的连接)和X通信,而不是物理性地让X看到包。注意图2的步骤2X知道TCP序列号PQ,因为X正确地接收到两个SYN包。没了LSR就不是这种情况了。
   
为了初始连接,每端主机发送一个初始的SYN包到他们的伙伴,虽然他们知道将不能到达目的地。他们这时嗅探包离开网络,记录序列号,并报告这个信息给XX需要这些包的TCP序列号,如此它将能够转播这些信息回到AB,那样他们就能够产生SYN+ACK包。两条路线所发的包都不会到达他们所标明地址的目的地。
   
更简单的方案是每个端点各发送一个不被考虑的SYN到他们伙伴。在接收端适当的设置NAT和防火墙,他们将由于没有映射存在而不会向前发送这些包到内部网络主机。一些NAT和一些防火墙将发送TCP重置包(RST)到这个不请自来的包的源地址。如果NAT产生RST包,AB不能简单的像图2里步骤1的建议一样发送一个SYN包到对方,因为在接受到RSTNANB将终止所建立的洞。如果NAT没有产生RST包,打开的TCP连接将不会突然终止。
   
另一种确保SYN包将不会到达它的目的网络的方法是发送带有低于伙伴的NAT路径长度的TTL值的SYN包。这包将会在去目的地的路上被明确地抛弃,并且TCP RST包将不会被任何发送者看到。更确切地说,一个ICMP过期包将被看到,并且产生一个问题,因为ICMP过期包突然地终止一个TCP连接。然而,如果使用者能够设置他们本地的防火墙抛弃ICMP包或者如果NAT不会发送ICMP消息包到它的内部网络,TCP连接的尝试将不会突然终止。
   
一个方案不能包括简单的欺骗源地址的SYN包,使发送者不会接收到ICMP包或者RST包。这样做会在中间件创建一个残废的映射。中间件在看到一个SYN包时,将创建一个从内部IP地址和端口到外部IP和端口的映射。然而,由于一个欺骗的SYN包有一个错误的源IP地址,映射将不会对应到内部网络的主机。此外,一个方案不能包括把TTL设置低到连中间件都看不到SYN包,因为这样做不会创建我们需要的允许外部后面发到内网的通信的映射。
   
假定一个<可预测的,可预测的,no LSR>环境,这种连接就像我们现在在图3所描述的。
    1.X
做了关于5.1节描述的端口预测。X预测到NA的下一端口是4000并预测到NB的下一端口是5000,并经由已经存在的连接告知AB
    2.A
B各自发送一个SYN包到对方,他们知道这个包将会被对方的NAT抛弃或者由于TTL过期而被抛弃。
     
aNA:4000NB:5000,SYN:P
     
bNB:5000NA:4000,SYN:Q
     
这一点是在各个端点的真实TCPconnect()函数调用所产生的。SYN包由TCP堆栈产生。这在NAT上创建了允许后面的来自伙伴IP地址和端口的通信通过并到达端点的映射。
    3.A
B各自发送他们自己所留意的ISNPQ)到X
     
aNA:3999X:1234,刚使用的ISNP
     
bNB:4999X:1235,刚使用的ISNQ
     
各个端点都需要它的伙伴的ISN,如此他们才能够构造合法的SYN+ACK包从而发到他们的伙伴。
    4.X
发送AB的对方各自所留意的ISNAB
     
aX:1234NA:3999,B刚使用的ISNQ
     
bX:1235NB:4999,A刚使用的ISNP
    5.A
B各自发送一个SYN+ACK包到对方
     
aNB:5000NA:4000,SYN+ACK:Q,P+1
     
bNA:4000NB:5000,SYN+ACK:P,Q+1
     
这是三次握手的第二部分。此外,AB重用了他们原来的序列号PQ作为在SYN+ACK中的序列号,并保证了所复制的序列号和应答号的最后状态和5.2节讨论的真实的TCP连接一样。
    6.A
B各自发送一个ACK包到对方,他们知道这包将会被对方的NAT抛弃或者由于TTL过期而被抛弃。
     
aNA:4000NB:5000,ACK:Q+1
     
bNB:5000NA:4000,ACK:P+1
      TCP
堆栈将自动地为我们发送这些ACK包来完成三次握手。我们不想ACK包到达他们的目的地,由于没有任何一方在等待ACK包。

   
作为步骤45而和情况1很相似的另一种方法,是X可以欺骗AB所需的SYN+ACK包。然而,我们为了某些类似在情况1中的原因选择了目前的方法。
   
由于步骤26在我们的技术中是可重复利用的,所以我们做了函数Case2(integer extPortA, integer extPortB)作为执行步骤26,用参数extPortAextPortB分别替代了外部端口40005000

5.6
情况3<随机的,可预测的,LSR>
A  X  B
|-------2a----->|  |
|  |-------2b----->|
|  |<------2c------|
|          Case1|(m,5000)       |
 
4:情况3
   
情况3<随机的,可预测的,LSR>类似于图2所描述的情况1。然而,X不能够预测到两个NAT中的一个的端口,比方说NAA首先不得不发送它的SYN包来允许X查看NA所选的端口。X将报告这一信息给B,因此B能够发送它的SYN包到正确的目标IP地址和端口。这个情况1的修改版在图4中描述并解释如下。
    1.X
做了关于5.1节描述的端口预测。X不能预测到NA的下一端口,但能够预测到NB的下一端口是5000,并经由已经存在的连接告知AB
    2.A
B同步经由X
     
aNA:mNB:5000,LSR:X,SYN:P
     
bXB知道NA工作于端口m
     
cNB:5000NA:mLSR:XSYN:Q
     
这两个SYN包是由TCPconnect()函数调用所产生。
     
这两个SYNNATNANB上各自创建了预期的映射。
    3.
调用Case1(m,5000)

5.7
情况4<随机的,可预测的,no LSR>
A  X  B
|-------2a----->|  |
|-------------->|  |
|-------------->|  |
|
  |  |
|----------
---->|-------3------>|
|<--------------|-------4-------|
|<--------------|---------------|
|<--------------|---------------|
|  |
  |
|<--------------|---------------|
|-------5------>|  |
|  |-------6------>|
|          Case2|(m,5000)       |
 
5:情况4
   
情况4的环境是<随机的,可预测的,no LSR>。我们已经为这个依靠于随机的且不拒绝一个带了残废的且对应于在NAT后主机在前面的初始连接的ACK或者校验和域的TCP包的NAT环境开发了一个方案。这方案被呈现在图5中并解释如下。
    1.X
做了关于5.1节描述的端口预测。X不能预测到NA的下一端口,但能预测到NB的下一端口是5000,并经由已经存在的连接告知AB
    2.A
发送TSYN包到B,这些包不是被对方的NAT所抛弃就是由于TTL过期而被抛弃。
      i = 0
      While i < T
          NA:rand
NB:5000, SYN:anything
          i = i+1
      End While
     
这会在NAT NA上创建T个映射,B将最后用SYN+ACK猜到的就是其中一个。
    3.X
通知B开始发送SYN+ACK包到NA
    4.B
发送许多SYN+ACK包到NA直到有一个到达A
      i = 1024
      While A
还没报告成功
          NB:5000
NA:i,
         
SYN+ACK:,anything,anything, Payload:i
          i = i+1
      End While
    5.A
报告穿过NAT的包负荷。
      NA:3999
X:1234,工作于端口m
      A
通过监听来自NB的任何SYN+ACK包的数据报,将可看到这个残废的SYN+ACK包。
    6.X
告诉B连接到A的端口m
      B
现在知道SYN包可以发向哪里。
    7.
调用Case2(m,5000)

   
在步骤2A所发送的TSYN包是独立于任何TCPconnect()函数调用。他们仅仅是使用在NAT上创建了T个映射的libnet库所产生的包。另一方面,Case2调用的步骤2所产生的SYN包是由ABTCPconnect()函数调用所产生的。这情况4环境的方案依靠于随机生成端口的NAT的行为。这方案依靠于拒绝带有错误的如序列号或者校验和域的TCP包的中间件。
    T
值能够被选择,像B在生成TSYN+ACK到随机目的端口号后有95%的机会猜到一个正确的外部端口。其实,ANAT随机地选择T的数目(它的外部端口数),这时B必须一直维持猜测直到在ANAT可选集中B选择到了一个。我们能够使用一个概率分析来构造一个高效的且最小工作量被AB所预算的设想。设PrGB猜到在T个实验中最少一个是正确的概率。价设ANAT已经在[102565535]的范围中选择了T个不同的端口号,如果B选择T个不同的端口号,在ANAT可选集中B不能选择到一个号的可能性是
    Pr_G =n-T/n * n-1-T/n-1 * n-2-T/n-2 * . . . * n-(T -1)-T/n-(T -1)
其中n是可能选择的端口数(n=65535-1024=64511)。
         T-1
    Pr_G =∏n-i-T/n-i
         i=0
反之,在T个实验中猜到一个是正确的可能性是
    PrG = 1-Pr_G
像之前的规定,T可能被选择如
    PrG > 95%
      T-1
    1-∏n-i-T/n-i> 95%
      i=0
计算T的量为T=439的这个乘积。
      439-1
    1-∏64511-i-439/64511-i=0.9506> 95%
      i=0
这结果说明如果A发送439个使在ANAT外部端口得到不同的随机的映射的SYN包,并且B发送许多不同的随机的到目的端口的SYN+ACK包,B在它发送第440AYN+ACK包之前就有大于95%的机会正确地猜测到439个外部端口映射的其中一个。
   
仅仅发送TSYN包的原因是这至少要使用两个资源,第一个是网络带宽的使用量,第二是在NAT上创建映射的数量。
5.8 情况5<随机的,随机的,LSR>
┌─────┐ ┌─────┐
NA端口了解NB端口了解|
└─────┘ └─────┘
   
           
   
       \  /     
   
        \/      
   
        /\      
   
       /  \     
┌─────┐ ┌─────┐
    A         B   
└─────┘ └─────┘
 
6:资源图表死锁
A  X  B
|-------2a----->|<------2b------|
|<------2c------|-------2c----->|
|-------3a----->|<------3b------|
|          Case1|(m,n)          |
 
7:情况5
   
在情况5中的环境是<随机的,随机的,LSR>。为了允许X同步到ABB必须要知道NA预先发送它的SYN包时所选的端口号。为了确定NA选择的端口,X不得不看ASYN包。ASYN包不能被发送直到X确定NB所选的端口号为止。这个死锁被制成图6的插图。A控制NA端口资源以致不外发SYN包,有效的预防了X知道NA所选的端口号。同样的,B也控制NB端口资源。在他们能够释放所控制资源之前,每端都需要对方的端口。我们让AB各发送两个SYN包可松散源路由穿过X且不连接到TCP connect()调用的方案来预防这个死锁。这两个SYN包在各自的NAT上创建了所需的映射并允许X获得两个资源,同时等同于情况12的类似方式连接。我们情况5的方案展示在图7中并解释如下。
    1.X
做了关于5.1节述的端口预测。X不能预测到NA或者NB的下一端口并经由已经存在的连接告知AB
    2.A
B都发送一个SYN包松散源路由穿过X
    
aNA:mNB:anything SYN:anything,LSR:X
    
bNB:nNA:anything SYN:anything,LSR:X
    
cX报告mB并报告nA
     
这两个SYN将在各自的NAT上创建所需的映射。
    3.A
B发送一个SYN到对方松散源路由穿过X
     
aNA:mNB:n,LSR:X,SYN:P
  
    bNB:nNA:m,LSR:X,SYN:Q
     
因为一致转换,即使目标端口和之前的步骤有所不同,NAT仍然为这个包利用所使用的相同映射(因此相同的外部端口号)。
    4.
调用Case1(m,n)

   
注意,SYN包发送步骤2不是关联到任何TCPconnect()函数调用,而更合适的,步骤3SYN包发送应归于一个TCPconnect()函数调用。同理,Case1的调用中SYN+ACK包发送步骤3不绑定到TCPaccept()函数子程序。

5.9
情况6<随机的,随机的,no LSR>
A  X  B
|-------2------>|<------2-------|
|-------------->|<--------------|
|-------------->|<--------------|
|
  |  |
|-------------->|<--------------|
|-------3-------|-------------->|
|<--------------|-------3-------|
|---------------|-------
------->|
|<--------------|---------------|
|---------------|-------------->|
|<--------------|---------------|
|
  |  |
|---------------|-------------->|
|<--------------|---------------|
|-------4------>|<------4-------|
|<------5-------|-------5------>
|
|          Case2|(m,n)          |
 
8:情况6
   
情况6的环境是<随机的,随机的,no LSR>。回顾图6的资源图表死锁,AB从包不可松散源路由保存端口的资源信息。这情况的方案被画成图8并解释如下。
    1.X
做了关于5.1节述的端口预测。X不能预测到NA或者NB的下一端口并经由已经存在的连接告知AB
    2.A
发送TSYN包到B同时B发送TSYN包到A,这些包将被在另一端的NAT抛弃或者由于TTL到期而被抛弃。
      i=0
      While i<T
          NA:rand
NB:rand,SYN:anything
          NB:rand
NA:rand,SYN:anything
          i=i+1
      End While
   
这些SYN包在两边的NAT上各创建了T个映射。
    3.B
A发送许多SYN+ACK包到他们的伙伴的NAT直到有一个到达他们的伙伴那里。
      i=1024
      While A
还没报告成功
          NB:rand
NA:i
   
       SYN+ACK:,anything,anything,Payload:i
          NA:rand
NB:i
          SYN+ACK:,anything,anything,Payload:i
          i=i+1
      End While
    4.A
B报告通过NAT的包负荷。
      NA:3999
X:1234,工作于端口m
      NB:4999
X:1235,工作于端口n
    5.X
告诉B连接到A的端口m并告诉A连接到B的端口n
      A
B现在知道他们的伙伴的外部端口号。
    6.
调用Case2(m,n)

   
情况6远比情况4困难,因为各个端点必须在对方的NAT上正确地猜到一个完整的映射〈源端口,目的端口〉。在情况4中,在非随机的NAT后的端点能够正确地猜到目的端口。当其中一个NAT是可预测时,源端口就被固定了。情况6的搜索空间是情况4的平方,替代64511种可能的是4161669121种结合需要猜测。
6. 实现
   
我们已经在LINUX工作站,通过调用libnetlibpcap使用C实现了第2种和第4种情况。第1356种情况没有实现。
   
协助者和端点都连接到由单独功能组成的库。协助者程序natblaster_server()只需提供其协助者所要监听的端口号。端点连接程序需要提供7个参数:(1)协助者的IP地址和(2)端口号,(3)本地端点外部IP地址,(4)内部IP地址,和(5)端口号,(6)伙伴外部IP地址,和(7)端口号。本地端点和伙伴的端口号必须由协助者帮助为试图的连接建立一个唯一标志符。三元组<本地外部IP,伙伴内部IP,伙伴内部端口>被用于在协助者上的唯一标志。库试图提供一个指定端口的套接字,然而,所返回的套接字不被保证是所指定的端口号。假设natblaster_connect()工作,库返回一个有效的套接字句柄。
   
为了测试我们的实现,我们在分离的网络上运行两个端点,每个都位于不同的且有效的NAT后面。第三部分的程序被运行于不在NAT之后的第三部计算机上。我们在英特网上做了比本地网络更多的测试,来确保测试更真实。
   
为了创建不会到达伙伴那里并不返回错误消息的包,我们设置了TTL值使其低到不会到达伙伴那里。设置低的TTL值由调用IP_TTL选项的setsockopt()系统调用完成。这选项也需要一个TTL值。这个值必须低于到伙伴的跳跃数,但必须要大于到外部最远的NAT的跳跃数。这套接字选项对于套接字的整个生存期来说必须不是持久不变的。例如,在三次握手成功之后,setsockopt()应该被再一次调用来提高 TTL值,这样后面的数据才确保能到达端点。依靠的是一个低的TTL只工作于是否一个ICMP TTL过期包不被端点的TCP堆栈看到,因为这过期包会导致在端点的套接字失败。我们所测试的NAT都不向前发送ICMP TTL过期包到内部网络。另一种方法是将发送普通包并希望伙伴的NAT默默地丢弃它们,然而,一些NAT可能发送RST包来响应那些未请自来的数据。这行为是详细的执行过程。我们没使用5.3节所描述的TTL决定技术;而是我们选择了我们知道是合适的并且低而普通的TTL值。
   
我们为连接前诊断实现了连续的端口分配方法,但没有实现一致转换。我们的实现没有使用一致转换。
   
我们的情况2和情况4的实现都非常成功并且能打开直接的TCP连接。情况2真实的打开了连接,而情况4有很高的几率是成功的(就是上面所讨论的,成功率取决于在预测相位的端口发送SYNSYNACK的数量)。
   
由于5.9节最后所给的原因,我们没有实现情况6。我们没实现情况135是因为LSR在英特网上不是典型地可用的并且我们相信这在实践中会有较低的成功率。
   
如前面所论述的,我们使用了增加系统调用所需的标准的Berkelet网络实现。例如,当我们发送一个SYN包但需要知道序列号时,这个SYN包由使用标准的connect()调用所发送的,之后首先开始一个线程来为所发的SYN包观测数据报。这线程能报告所使用的序列号。
   
情况2和情况4必须有root的执行权,因为这是libnetlibpcap所要求的。由于无需欺骗或者探嗅,第三方可以以一般用户的权限运行。

7.
总结
   
我们已经证明了如何在两个不同的典型的NAT后面的主机之间建立直接的TCP连接,这些解决方案都没有以任何方式改变TCP/IP栈,而是为这些主机建立连接起到了杠杠作用。我们的方案可以为很多的程序所应用,从点对点的通信到即时消息通信。对于这个问题已经存在解决方法包括代理都没有有效地利用网络资源并且伸缩性不好。
   
随着IPv6的到来,NAT也许就不再是个网站的组成了,但是,这些情况包括可预测NAT也可以被应用到使用状态的防火墙后面的主机。跟NAT相似,状态防火墙有能力只允许从他们所包含的内部网络发起的连接。我们的解决方案双方都可以初始话一个这些防火墙都允许的TCP连接。我们的几种方案在配置有IDSes的场合是不可取的,因为在第四和第六种情况下,都使用了类似于端口扫描的技术。这种情况下最后关闭这样的网络监视设备。尽管如此,我们地解决方案对于大部分的网络来说一般是足够的,甚至对于那些可能都不存在的使用随机分配地址的NAT来说也是适用的。

8.
参考文献
[1] Bryan Ford. NatCheck: Hosted by the MIDCOM-P2P
    project on SourceForge.
    http://midcom-p2p.sourceforge.net.
[2] Bryan Ford, Pyda Srisuresh, and Dan Kegel. Peer-to-Peer
    Communication Across Network Address Translators. In
    USENIX Annual Technical Conference, Anaheim, CA, April
    2005.
[3] Groove Networks. http://groove.net.
[4] Saikat Guha, Yutaka Takeday, and Paul Francis. NUTSS: A
    SIP-based approach to UDP and TCP Network Connectivity.
    In SIGCOMM 2004 Workshops, Aug 2004.
[5] M. Holdrege and P. Srisuresh. Protocol Complications with
    the IP Network Address Translator. RFC 3027, Internet
    Engineering Task Force, January 2001.
[6] Hopster: Bypass Firewall Bypass Proxy Software.
    http://www.hopster.com.
[7] Information Sciences Institute. Transmission Control
    Protocol (TCP). RFC 793, Internet Engineering Task Force,
    September 1981.
[8] Brad Karp, Sylvia Ratnasamy, Sean Rhea, and Scott
    Shenker. Spurring Adoption of DHTs with OpenHash, a
    Public DHT Service. In Proceedings of the 3rd International
    Workshop on Peer-to-Peer Systems, Feb 2004.
[9] Y. Rekhter, B. Moskowitz, D. Karrenberg, G. J. de Groot,
    and E. Lear. Address Allocation for Private Internets. RFC
    1918, Internet Engineering Task Force, February 1996.
[10] J. Rosenberg, J. Weinberger, C. Huitema, and R. Mahy.
     STUN - Simple Traversal of User Datagram Protocol (UDP).
     RFC 3489, Internet Engineering Task Force, September
     2003.
[11] P. Srisuresh and K. Egevang. Traditional IP Network
     Address Translator (Traditional NAT). RFC 3022, Internet
     Engineering Task Force, January 2001.
[12] P. Srisuresh and M. Holdrege. IP Network Address
     Translator (NAT) Terminology and Considerations. RFC
     2663, Internet Engineering Task Force, August 1999.
[13] P. Srisuresh, J. Kuthan, J. Rosenberg, A. Molitor, and
     A. Rayhan. Middlebox communication architecture and
     framework. RFC 3303, Internet Engineering Task Force,
     August 2002.
[14] Jason Thomas, Andrew Mickish, and Susheel Daswani. Push
     Proxy: Protocol Document 0.6, June 2003.
[15] Michael Walfish, Jeremy Stribling, Maxwell Krohn, Hari
     Balakrishnan, Robert Morris, and Scott Shenker.
     Middleboxes No Longer Considered Harmful. In
     Proceedings of USENIX Symposium on Operating Systems
     Design and Implementation, December 2004.
 
相关测试代码请看
http://sourceforge.net/projects/natblaster

[1] [2]

责任编辑 webmaster

 
发表评论  打印本文  推荐本文  加入收藏  返回顶部  关闭窗口
 
 
 
 
评论更多>>
 
 
 
发表
 
姓名: QQ:
性别: MSN:
E-mail: 主页:
评分: 1 2 3 4 5
评论内容:
验证码:
  
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  •