通过middlebox实施P2P通讯三[传]

类别:编程语言 点击:0 评论:0 推荐:

3.3.4 Consistent prot binddings(保持端口绑定)
 hole punching 技术有一个需要注意的地方:它只能工作在两台NAT都是cone NAT(或没有NAT 防火墙)的情况下,只要UDP端口还在使用,它就需要保持一个固定的端口把一个给定(私有IP,私有UDP端口)和一个(公共IP,公共UDP端口)绑定。象对称NAT一样,为每个新的连接会话分配一个新的公共端口,对一个UDP应用程序来说,为了和不同的外部通讯重用一个已经存在的地址转换是不可以的。(这边稍微有点糊涂,再多看看。) 既然cone NAT运用是相当普遍的,UDP hole punching技术应用的也相当广泛,但是还有一小部分是对等NAT配置,因此不能支持这种技术。

 3.4 UDP port number prediction

 有关UDP hole punching技术在上面已经被讨论过,它可以允许在一些对等NAT存在的地方也能建立P2P UDP连接会话。这种方法有时被称为"N+1"技术 [BIDIR ]并且由Takeda[SYM-STUN]详细介绍。这种方法分析NAT的工作方式并且试图预测它为将来的连接会话分配的公共端口。再次考虑那两个客户的状态,A和B,在各自分开的NAT后面,已经与一台拥有永久地址的服务器S建立了UDP连接。
                                  Server S
                               18.181.0.31:1234
                                      |
                                      |
               +----------------------+----------------------+
               |                                             |
        Symmetric NAT A                               Symmetric NAT B
    A-S 155.99.25.11:62000                        B-S 138.76.29.7:31000
               |                                             |
               |                                             |
            Client A                                      Client B
         10.0.0.1:1234                                 10.1.1.3:1234

 NAT A分配一个属于自己的UDP端口62000以在A和S之间建立通讯连接,而NAT B分配一个31000端口用于在B和S之间建立连接。通过与服务器的通讯,A和B可以从服务器S上得到对方的公共IP地址和端口号。客户端A现在发送一个UDP数据包到地址138.76.29.7,端口31001(注意端口数目的增加),而客户端B同时发送一个数据包到地址的155,99.25.11,端口62001上。如果NAT A和B依次为新的连接分配端口,如果从A-S和B-S连接建立后没过多少时间,那在A和B之间的一个双向通讯通道就可以工作起来。A到B的数据包让NAT A建立一个新的连接,NAT A(所期望的)分配一个公共端口62001,因为之前A和S的连接会话用的62000端口,接下来就是62001。同样的,B到A的数据包将让NAT B打开一个新连接,并将(也是所期望的)分配一个端口31001。如果客户端可以正确的预测到NAT为新的连接分配的端口,一条双向的UDP通讯通道就会象如下图所示一样建立起来。

                                  Server S
                               18.181.0.31:1234
                                      |
                                      |
               +----------------------+----------------------+
               |                                             |
             NAT A                                         NAT B
    A-S 155.99.25.11:62000                        B-S 138.76.29.7:31000
    A-B 155.99.25.11:62001                        B-A 138.76.29.7:31001
               |                                             |
               |                                             |
            Client A                                      Client B
         10.0.0.1:1234                                 10.1.1.3:1234


 显而易见有很多情况都能导致这种方法失败。假如任意一个预测的端口碰巧已经被其他无关的连接占用,NAT将会错过正确的端口,连接尝试也将失败。假如任意一个NAT有时或者总是选择非连续的端口号,这个方法也将失败。假如在A(B)建立了它和S的连接之后,但在发送第一个数据包到B(A)之前,一个不同的客户端在NAT(也或者B)打开一个新的外部连接到任何外部主机,无关的客户端会不注意的"偷"了(A TO B或者B TO A)所要求的端口。因此在任一NAT都包含不止一台客户端时,这种方法很少使用。

 实际上,如果那些NAT是cone NAT,或者一个是cone NAT,另一个是对称NAT,这种情况下的P2P应用程序依然需要工作,应用程序需要实现查明在任何一个上与end [STUN]有关的NAT是哪一钟,并按此来修改它的工作方式,这样增加了算法的复杂程序并让网络变的脆弱。最终,假如任何一方客户端在2级以上的NAT下并且离客户端最近的NAT是对称的,预测端口的方式是无法工作的。对所有这些原因来说,应用程序是无法实现这种方法的,在这里被提及是为了历史和信息目的(就是告诉大家有这么回事,我想)

 3.5. Simultaneous TCP open(TCP同时打开)
 在一对节点都在已存在middlebox后,有一种建立直接P2P TCP连接的方法有时候会被使用。大多数TCP连接都是从一个终端发从一个SYN包到另一个终端,另一个中断同步响应一个SYN-ACK包。无论怎样,对于两个终端来说,同时通过发送同步包到对方然后用一个ACK包应答来建立一个TCP连接是可行的。这种过程就被称为"simultaneous open"(同时打开)

 如果一个middlebox从尝试建立一个TCP连接的私有网络的外面接受一个TCP SYN包,middlebox通常以丢弃这个SYN包或者发送一个TCP RST(连接复位)包的方式来拒绝这个连接尝试。但是,如果同步包与源和目的地址端口一起到达,那么会让middlebox相信一个TCP连接已经建立起来,然后middlebox将会允许数据包通过。特别是如果middlebox刚刚得到并转换了一个从同样地址和端口来的SYN包,它将认为连接是成立的并允许进来的SYN通过。如果客户端A和B能彼此预测公共端口,它们各自的middlebox将分配下一个TCP连接端口,如果其中一个客户端和另一个客户端建立一个外部的TCP连接,可以在对方SYN到达本地middlebox之前就发送SYN包通过它本地自己的middlebox,那么P2P TCP连接就可以工作了。

 令人遗憾的是,这个方法也可能比上面说的UDP端口号预测方法更脆弱并对时效更加敏感。首先,除非在进行TCP连接时,两个middleboxes是简单的防火墙或者cone NAT,在各自尝试猜测公共端口号来让NAT分配新的连接时,和上面(UDP端口预测)说到的完全一样的事情会导致连接失败。另外,如果有一方的客户发送的同步包太迅速的到达对面的middlebox,远端middlebox可能会用一个RST包拒绝SYN包,接下来就会导致本地的middlebox关闭对话并且在将来SYN重发时使用了相同但无用的端口号。最终,对simultaneous open的支持作为一个TCP的特殊应用,没有在广泛的系统中被使用。因此,这个方法也只为历史因素在这里被同样提及;它不建议被应用程序使用。在现有NAT上想要实现P2P直接通讯的应用程序应该使用UDP。

 4. Application design guidelines(应用程序设计思路)

 4.1 What works with P2P middleboxes(如何和P2P middlebox一起工作)
 既然UDP hole punching是在两个都位于NAT后的主机之间建立P2P直接通讯方法中最有效率的一个,并且它可以在多种现有NAT上使用,如果要求建立有效的P2P通讯,通常建议这种方法,但当直接通讯不能建立时,就得依靠简单的传播。(还不怎么明白)

 4.2 Peers behind the same NAT(主机在同一个NAT后面)
 实际上有相当数量的用户不止2个IP地址,会有3个或者更多的IP地址。这样的话,告诉登录服务器究竟是哪一个地址变的就有些困难了。因此在这种情况下,应用程序应该发送它所有的IP地址。

 4.3 Peer discovery(主机发现)

 应用程序会发送一些数据包到几个地址,以发现哪一个地址是最合适的,应用程序可能变成(后面的不太明白,自己理解吧,sorry), 由于主机可能会不恰当的选择一个路由地址当做一个内部局域网(例如11.0.1.1,已经被DOD网络分配,DOD是一种网络模型)。因此应用程序应该小心的发送推测的呼叫包。
 申请把包送到几地址发现, 哪一个适宜适合一规定贵族使用可能成为一个乱扔净价的'' 空间废品''的显著的源头,

 4.4 TCP P2P applications (TCP P2P应用程序)

 被程序员们广泛使用的SOCKET API,常用于C/S结构应用设计中。在它的通常使用方式中,一个SOCKET能绑定一个TCP或UDP端口。一个应用程序不会被允许用同样的端口(TCP or UDP)和多个SOCKET绑定来和多个外部主机同时建立连接(或)用一个SOCKET在端口上监听而其他SOCKET来建立外部连接。但是上述单个SOCKET的端口绑定限制在UDP上不是问题,因为UDP是基于数据报文的协议。UDP P2P应用程序设计者可以用recvfrom()和sendto()函数来让一个SOCKET不仅发送而且可以从多个主机上接受数据报文。

 这不是TCP具有的情况。由于TCP,每个输入和输出连接都要和一个单独的SOCKET有联系。Linux Sockets API用SO_REUSEADDR选项的帮助来解决这个问题(是不是应该这么说?),这个选项好象不起作用,但可以
 (在标准Single Unix里没有这个函数)。Win32 API提供了一个相同的调用SetReuseAddress。使用任何上述的选择,应用程序可以复用一个TCP端口的多个SOCKET。就是说,可以打开两个绑定在同样端口上的TCP stream Socket,一个用与listen(),另一个用与其它主机connect()

 4.5 Use of midcom protocol()

 如果应用程序知道它们需要穿越的middlebox并且这些middlebox实现midcom 协议,应用程序能使用midcom协议更容易的穿越middlebox。
 例如,P2P应用程序需要NAT middlebox保持终端端口的绑定状态。假如middlebox可以支持midcom,P2P应用程序可以控制修改绑定端口(或者绑定地址)的参数,例如生存时间,maxidletime(?),因此应用程序不仅可以直接的连接外部主机而且也可以从外部主机接受连接;这样就不需要定期保持端口绑定的状态。当应用程序不再需要绑定,也可以使用midcom协议简单的取消绑定。

 5. NAT Design Guidelines (NAT设计指导)
 这部分讨论网络地址转换的设计,他们会影响P2P应用程序。

 5.1 Deprecat the use of symmetric NATs (不赞成使用对等NAT)
 对等NAT在那些C/S结构的应用中比如网络浏览中得到广泛应用,它们只需要建立一个向外的连接即可。但是现在,比如实时消息和语音会议等P2P应用程序被广泛的应用。对等NAT不能支持保留终端的定义并且不适用于P2P应用程序。不建议使用对等NAT来支持P2P应用程序。
 一个P2P-middlebox必须在UDP通讯时具备Cone NAT的特点,允许应用程序可以建立使用UDP hole punching技术建立稳定的P2P连接。理论上,一个P2P-middlebox应该也允许应用程序既可以经过TCP,也可以通过UDP建立P2P连接。

 5.2 Add incremental cone-NAT support to symmetric NAT devices (增加递增的cone-NAT以支持对等NAT设备)

 一种可以让对等NAT设备扩展支持P2P应用程序的是分配它的可转让的端口空间,为一到一的连接预订一个合适的端口,为一个一到多的连接预订合适的一套不同的端口。
 更进一步(未来?),一个NAT装置可以明确的被那些P2P应用程序和主机配置,因此NAT装置可以自动由正确的端口数据块来分配一个P2P端口。

 5.3 Maintain consisten port bindings for UDP ports (保持UDP端口的绑定)
 这份资料对NAT设计者最主要和最重要的建议是NAT保持一个固定的端口,绑定一个给定的(内部IP地址,内部UDP端口)和一个相应的(公共IP地址,公共UDP端口)
 只要有任何连接存在并使用这个端口绑定,这个端口绑定就要存在。通过检查每一个包的源和目的IP地址和端口号,NAT可能会过滤关于每一个连接基础的数据包(? 俺8懂)。当在一个私有网络上的节点建立了一个新的外部连接时,使用了一个现有的已经转换过的UDP连接会话的IP地址和UDP端口号,NAT应该保证新的UDP连接作为现有连接给定一个同样的公共IP地址和UDP端口。

 5.3.1 Preserving port numbers(保持端口号)  (就是客户端用啥端口,NAT分配啥端口这个意思吧)
 一些NAT,当建立一个新的UDP连接时,会尝试给一个相应的私有端口号分配一个同样的公共端口号,如果这个端口号碰巧是可用的。例如,假如地址是10.0.0.1的客户端A用一个从端口1234发送的数据包建立一个外部的UDP连接,NAT的公共端口1234碰巧是可用的,那么NAT会为连接使用NAT公共IP地址上的端口号1234作为转换客户端A的地址。由于如果内部网络的最多一个节点正在使用这个端口号,它是对一个NAT保持端口唯一可行的方法,这种方式可能对一些希望只用特别的UDP端口号的过去的UDP程序有帮助,但不建议应用程序依靠这种方式。
 另外, 一个NAT不应该在一个新连接中保持端口号,如果确实如此将与保持公共和私有终端地址绑定的目的相抵触。例如,假定客户端A在内部的1234端口上与外部服务器S建立了一个连接,NAT A已经为这个连接分配了公共端口62000,因为端口号1234在NAT上此时是不可用的。现在假想在NAT上的端口号1234后来可以使用了,而此时A和S的连接仍然存在,客户端A用同样的内部端口1234建立一个新的连接到外部节点B上。在这种情况下,因为端口绑定已经在客户端A的端口1234和NAT的公共端口62000上建立,所以这个绑定应该继续保持,新连接也应该用62000端口作为公共端口,来对应客户端A的端口1234。NAT不应该仅仅因为端口1234变的可用了就为新的连接分配公共端口1234:这种特点不可能在任何情况下都对应用程序有帮助,由于应用程序已经对一个转换的端口号进行操作,并且它会中断应用程序用UDP hole punching技术建立P2P连接的尝试。

 5.4 Maintaining consistent port bindings for TCP ports (为TCP端口保持端口绑定)
 和UDP地址转换的特点一致,cone NAT也应该对TCP连接保持私有和公共IP地址,TCP端口号的绑定不变,就如上面的关于UDP描述的方式一样。保持TCP终端绑定不变将增加NAT对P2P TCP应用程序在从同样源端口建立多个TCP连接时的兼容性。

 5.5 Large timeout for P2P applications (P2P程序的大超时?)
 我们推荐middlebox在P2P应用时使用的最小超时大约5分钟(300秒),即,在P2P应用时为端口绑定或为分配端口时,来给middlebox配置这个空闲超时时间。当middlebox惯用目前配置时,就常常尝试使用更短的时间。但是更短的超时时间是有些问题的。考虑一个有16个终端节点的P2P应用程序,他们将每10秒发给网络一个保持活动状态的数据包以避免NAT超时。这样做是因为一个可能会以middlebox超时时间的5倍发送保持活动的数据包,在这种情况下,保持活动的包将在网络上被丢弃。

 5.6 Support loopback translation(支持自环转换)
 我们强烈建议middlebox 支持自环转换,允许在一台middlebox后面的主机可以和其它位于同一middlebox后的主机通过它们的可能被转换的公共端点通讯。支持自环转换是相当重要的,特别是在那些大容量多层NAT中,作为第一级的NAT。如第3.3.3 部分的描述,位于同一台一级NAT下,但是第二级NAT不同的主机无法通过UDP hole punching彼此通讯,即使全部middlebox保持端点在NAT上的映射不变,除非第一级NAT支持自环转换。

本文地址:http://com.8s8s.com/it/it27297.htm