




已阅读5页,还剩13页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
一:问题背景 多媒体会话信令协议是在准备建立媒体流传输的代理之间交换信息的协议,例如SIP、RTSP、H.323等。媒体流与信令流截然不同,它们所采用的网络通道也不一致。由于协议自身设计上的原因,使得媒体流无法直接穿透网络地址转换/防火墙(NAT/FW)。因为它们生存期的目标只是为了建立一个在信息中携带IP地址的分组流,这在遇到NAT/FW 时会带来许多问题。而且这些协议的目标是通过建立P2P(Peer to Peer)媒体流以减小时延,而协议本身很多方面却与NAT存在兼容性问题,这也是穿透 NAT/FW的困难所在。而NAT仍是解决当前公用IP地址紧缺和网络安全问题的最有力手段,它主要有四种类型:完全圆锥型NAT(Full Cone NAT),地址限制圆锥型NAT (Address Restricted Cone NAT),端口限制圆锥型NAT (Port Restricted Cone NAT),对称型NAT (Symmetric NAT)。前三种NAT,映射与目的地址无关,只要源地址相同,映射就相同,而对称型NAT的映射则同时关联源地址和目的地址,所以穿透问题最为复杂。二:NAT简介NAT:网络地址转换(Network Address Translators)NAT的演变种类:1:基本NAT基本的NAT实现的功能很简单,在子网内使用一个保留的IP子网段,这些IP对外是不可见的。子网内只有少数一些IP地址可以对应到真正全球唯一的IP地 址。如果这些节点需要访问外部网络,那么基本NAT就负责将这个节点的子网内IP转化为一个全球唯一的IP然后发送出去。(基本的NAT会改变IP包中的 原IP地址,但是不会改变IP包中的端口),互联网最开始使用的是基本NAT.2:NAPTNAPT是经NAT演变后的变种。NAPT不但会改变经过这个NAT设备的IP数据报的IP地址,还会改变IP数据报的TCP/UDP端口目前一般常见的是NAPT。三:NAT种类1:非对称型NATa)完全圆锥型NAT打洞创建原则:终端向外部任意IP发送一个package,NAT就形成了一个映射,即创建了一个洞。接收数据原则:只要过来的数据是发送到打洞的终端,就可以顺利通过。具体来说就是,如图所示,NAT会将客户机地址X:y转换成公网地址A:b并绑定,任何包都可以通过地址A:b送到客户主机的X:y地址上b)受限圆锥型NAT打洞创建原则:终端向外部某个IP发送一个package,就形成了与此IP的一个映射。接收数据原则:满足两个条件:1,此数据来自此IP;2,此数据要发送到打洞的终端。具体的说就是,如图所示,NAT会将客户机地址X:y转换成公网地址A:b并绑定,只有来自主机P的包才能和主机X:y通信。c)端口受限圆锥型NAT打洞创建原则:终端向外部某个IP的某个Port发送一个package,NAT就形成了与此IP/Port对的一个映射。接收数据原则:满足两个条件:1,此数据来自此IP的此Port;2,此数据要发送到打洞的终端。具体来说就是,如图所示,NAT会将客户机地址X:y转换成公网地址A:b并绑定,只有来自主机P,q的包才能和主机X:y通信。2:对称型NAT对称NAT是指把所有来自相同内部IP地址和端口号,到特定目的IP地址和端口号的请求映射到相同的外部TP地址和端口。如果同一主机使用不同的源地址和端口对,发送的目的地址不同,则使用不同的映射。只有收到了一个IP包的外部主机才能够向该内部主机发送回一个UDP包。 对称的NAT不保证所有会话中的(私有地址,私有端口)和(公开IP,公开端口)之间绑定的一致性。相反,它为每个新的会话分配一个新的端口号。具体的说就是,如图所示,NAT会将客户机地址X:y转换成公网地址A:b并绑定为 X:y|A:bP:q,NAT只接受来自P:q的incoming packet,将它转给X:y ,每次客户机请求一个不同的公网地址和端口时,NAT就会新分配一个端口号C,d。四:穿越NAT/firewall的几大方式NAT穿越的核心思想就是让p2p的双方的NAT看上去都是“向外”的NAT。1:转发方式最可靠但同时也是效率最低的p2p穿越NAT进行通信的方法是采用类似C/S方式的转发。假定两个节点A和B每个节点都有向外的TCP或UDP 连接,联入公共的已知服务器S,S的公网IP地址是1,端口号是1234(如图所示),每个客户端位于不同的私有内网中,并且它们 的NAT设备妨碍了客户端之间直接的p2p连接。做为对直连方案的替代方案,两个客户端可以利用公共的服务器S进行消息的转发。例如,A为了将消息送给 B,A只需将消息发给S,然后由S转发给B,这一过程将使用A与B事先与S建立好的连接。转发方式通常只能在双方客户端都连接到服务器的时候有效。这种方式的缺点在于,它假定服务器的处理能力和网络带宽以及通信延迟都是理想的情况 下,不会受到客户端个数的影响。但是,由于没有其它的方法能够像转发方式那样,可以穿越现存的所有NAT设备,因此在构建高可靠性的p2p系统的时候,通 过服务器转发的方式依旧是一个非常有用的保证系统可靠性的方法。TURN协议定义了如何实现安全的转发方式。2:反向连接方式一些p2p的应用程序采用了直接但是有所限制的技术来实现NAT穿越,该技术叫做“反向连接”,这是用于当两个节点联入服务器S的时候,只有一个节点在NAT设备的后面(如图所示)。如果A希望建立与B的连接,那么A可以直接联入B,因为B是在公网中存在的,没有经过NAT转换,而且A的 NAT设备也允许A直接由内网发起向外网的连接。如果B希望建立与A的连接,很不幸,A的NAT设备会阻止该操作,此时,B可以借助于转发服务器S,向A 发送“反向连接”请求,由A“主动”连接B,从而达到A与B的p2p通信的目的。尽管该技术的局限性非常明显,但是使用已知的服务器做为中介辅助p2p客户端双方进行p2p连接的思想已经成为了更加通用的“打洞”技术的基本 思想。3:UDP打洞方式即使两个p2p客户端都位于NAT设备后面,UDP打洞方式也能够通过已知的服务器实现p2p客户端直连。该技术在RFC 3027的第5.1节中曾有所提及,在网络上可以找到对其较模糊的描述,在最近的IP协议实验中得到应用,在多种在线游戏协议中得到了应用。e在基于UDP的Hole Punching场景中,终端A、B各自向服务器注册,服务器因此知道两者的 私网地址和NAT转换后的公网地址。当A希望与B建立连接时,A首先向服务器发送连接请 求,服务器将B的公网和私网地址返回给A,同时,服务器将A的连接请求和A的公网及私网 地址发给B。此时A和B都知道了彼此的公网和私网地址。需要注意的是A、B彼此与服务器 之间的通讯可以顺利穿透NAT是因为A、B都通过向服务器注册在彼此的NAT设备上打开了 通往服务器的“Hole”(即NAT Binding),同时通过不断发送keep alive消息保持此Hole的 存在。在得到B的公网和私网地址后,A同时向这两个地址发起连接。在A和B同处于一个NAT之后 的极端情况下,B将首先在私网地址上收到A的连接请求,A与B之间的通讯不会有NAT的介 入。在A和B处于不同的NAT之后的情况下,A发往B私网地址的连接将会无法路由或者被错 误路由到不相关的终端从而被丢弃。发往B公网地址的连接将会顺利到达B所在的NAT。同 样的情况发生在B,即B也同时向A的两个地址发送连接请求。当A发往B的包先与B发往A的 包到达NAT 2,由于NAT中的绑定是只有包从NAT内往外发时才会建立,因此A发往B的包 将被丢弃,NAT穿透不成功。当B发往A的包经过NAT 2之后,NAT绑定:37000 - :12345得以建立,后续的A发往B的包因此可以经过此绑定顺利被B接收,NAT穿透 完成。而B发往A的包到达A所在的NAT 1时,由于A已经通过向B发包在NAT 1中建立了绑 定:37000 - :23456,因此可以顺利通过NAT。由于A、B是异步同时向对方 发包,因此在上文中描述的角色并不固定,当B发往A的包先与A发往B的包到达NAT 1时, 两者角色互换。 3.1集中服务器打洞技术假定客户端A和B可以与公网内的已知的集中服务器建立UDP连接(可以互发UDP数据包)。当一个客户端在S上登陆的时候,服务器记录 下该客户端的两个endpoints(IP地址,UDP端口),一个是该客户端确信自己是通过该ip和端口与服务器S进行通信的,另一个是服务器S记录下 的由服务器“观察”到的该客户端实际与自己通信所使用的ip和端口。我们可以把前一个endpoint看作是客户端的内网ip和端口,把后一个 endpoint看作是客户端的内网ip和端口经过NAT转换后的公网ip和端口。服务器可以从客户端的登陆消息的消息体中得到该客户端的内网 endpoint相关信息,可以通过对登陆消息的IP或UDP头得到该客户端的公网endpoint。如果该客户端不是位于NAT设备后面,那么采用上述 方法得到的两个endpoint的值应该完全相同。也有一些“弱智”的NAT设备会扫描UDP数据包的包体,寻找4字节的位域,看上去很像IP地址的位域,并且把它们改为与IP头一样的地址。为 了避免这种行为的NAT设备对UDP数据包包体的修改,应用程序可以采用直接对IP地址的值进行加密的方式骗过NAT设备的检查。3.2建立p2p的session假定A要发起对B的直接连接,“打洞”过程如下所示:(endpoint指ip地址和端口的配对)(1)A最初不知道如何向B发起连接,于是A 向服务器S发送消息,请求S帮助建立与B的UDP连接。(2)S将含有B的公网和内网的endpoint发给A,同时,S将含有A的公网和内网的endpoint的用于请求连接的消息也发给B。一旦 这些消息顺利到达,A与B就都知道了对方的公网和内网的endpoint。(3)当A收到由S发来的包含B的公网和内网endpoint的消息,A开始向这些B的endpoint发送UDP数据包,并且A会自动锁定第 一个给出响应的B的endpoint。同理,当B收到由S发来的A的公网和内网endpoint以后,也会开始向A的公网和内网的endpoint发送 UDP数据包,并且自动锁定第一个得到A的回应的endpoint。由于A与B的互相向对方发送UDP数据包的操作是异步的,所以A和B发送数据包的时间 先后并没有严格的时序要求。进行UDP“打洞”方式可以分三种情况具体讨论。第一种也是最“简单”的一种情景,两个客户 端都位于同一个NAT设备后面,位于同一个内网中;第二种也是最普遍的一种情景,两个客户端分别位于不同的NAT设备后面,分属不同的内网;第三种是客户 端位于两层NAT设备之后,通常最上层的NAT是由ISP网络提供商,第二层的NAT是家用的NAT路由器之类的设备。通常情况下由应用程序自身确定的网络物理层连接方式是很困难的,有时甚至是不可能的,即使是上述的若干种情景下可以穿越NAT,也只是代表在一 定时期内有效,而不是永久有效的。诸如STUN之类的网络协议或许可以提供必要的NAT信息,但在遇到多层NAT设备的时候,通常这些信息也不是完全完整 和有效的。尽管如此,只要NAT设备的响应是“合理”的,在通常情况下“打洞”技术还是能够在应用程序对网络状况一无所知的前提下自动适用于多数场 合。下面将逐个介绍各种UDP”打洞”方法。3.2.1 p2p客户端位于同一个NAT设备后面首先假设两个客户端位于同一个NAT设备后面,并且位于相同的内网(相同的私有IP地址域)如图所示。A与S建立了UDP连接,经过NAT转 换后,A的公网端口被映射为62000。B同样与S建立了UDP连接,公网端口映射为62005。假设A想通过服务器S做为介绍人,发起对B的连接。A向S发出消息请求与B进行连接。S将B的公网endpoint(即公网ip和port)以 及内网endpoint(即内网ip和port)发给A,同时把A的公网、内网的endpoints发给B。由A和B发往对方公网endpoint的 UDP数据包能否被对方收到,取决于当前的NAT是否支持“发夹”转换(hairpin转换,也就是同一台设备,不同端口之间的UDP数据包能否到达)。但是A与B往对方内网endpoint发送的UDP数据包是一定可以到达的,无论如何,内网数据包不需要路由,并且速度更快。A与B有很 大的可能性采用内网的endpoint进行常规的p2p通信。假定NAT设备支持“发夹”转换,应用程序也忽略由内网endpoint的连接,那么A、B会采用公网endpoint做为p2p通信的连接, 这势必会造成数据包无谓地经过NAT设备,这是一种对资源的浪费。我们会在第六节讨论这种情况,毕竟支持“发夹”转换的NAT设备还远没有对“打洞”技术 支持的NAT设备多。就目前的网络情况而言,应用程序在“打洞”的时候,最好还是把公网endpoint和内网endpoint都实验一下。3.2.2p2p客户端位于不同的NAT设备后面假定A与B在不同的NAT设备后面,分属不同的内网,如图所示。A与B都经由各自的NAT设备与服务器S建立了UDP连接,A与B的本地端口 号均为4321,服务器S的公网端口号为1234。在“向外”session中,A的公网IP被映射为1,公网端口为62000, B的公网IP被映射为,公网端口为31000。如下所示:客户端A-本地IP:,本地端口:4321,公网IP:1,公网端口:62000 客户端B-本地IP:,本地端口:4321,公网IP:,公网端口:31000在A向服务器S发送的登陆消息体中,会包含A的内网endpoint信息,即:4321;服务器S会记录下A的内网 endpoint,同时会把自己观察到的A的公网endpoint记录下来,即1:62000。同理,服务器S会记录下B的内网 endpoint,:4321和由S观察到的B的公endpoint,:31000。无论A与B二者任何一方向 S发送p2p连接请求,服务器都会将其记录下来的上述的公网、内网endpoint发送给A、B。由于A、B分属不同的内网,它们彼此的内网endpoint无法在公网中路由,所以发往各自内网endpoint的UDP数据包会发送到错误的 主机或者根本不存在的主机。因此应用程序对于收到的消息必须经过授权和过滤,只有通过授权的的消息才能是从对方的endpoint发出来的,例如,可以在 消息中加入对方的程序名称、加密算法,或者至少是一个双方都从服务器S上的预先得到的随机数字。现在假定A的第一个消息将发往B的公网endpoint,如上图所示。该消息途经A的NAT设备,并在该设备上生成了一个“向外”的 session。新的session源endpoint是:4321该endpoint和A与服务器S的建立连接的时候NAT生成的源 endpoint一样,但它的目的endpoint不同。如果A的NAT设备给出的响应是“友好”的,那么A的NAT设备将保留A的内网 endpoint,并且所有来自A的源endpoint(:4321)的数据包都沿用A与S事先建立起来的session,公网 endpoint均为(1:62000)。A向B的公网endpoint发送消息的过程就是“打洞”的过程,从A的内网的角度来看 应为从(:4321)发往(:31000),从A在其NAT设备上建立的session来看,是从 (1:62000)发到(:31000)。如果A发给B的公网endpoint的消息包在B向A发送消息包之前到达B的NAT设备,B的NAT会认为A发过来的消息是未经授权的公网消息,会丢弃掉该数据包。B发往A的消息包根上述的过程一样,会在B的NAT上建立一个(:4321,1: 62000)的session(通常也会沿用B与S连接时建立的session,只是该session现在不光可以接受由S发给B的消息,还可以接受从A 的NAT设备-1:6200发来的消息)一旦A与B都向对方的NAT在公网上的endpoint发送了数据包,就打开了A与B之间的“洞”,A与B向对方的公网endpoint发送数 据,等效为向对方的客户端直接发送UDP数据包了。一旦应用程序确认已经可以通过往对方的公网endpoint发送数据包的方式让数据包到达NAT后面的 目的应用程序,程序会自动停止继续发送用于“打洞”的数据包,转而开始真正的p2p数据传输。3.2.3p2p客户端位于多层NAT设备后面有的网络拓扑结构包含了多个NAT设备,如果没有掌握该拓扑结构的详细信息,两个客户端之间是无法建立“最优化”的p2p路由的。现在我们来讨 论最后一种情况,如下图所示。假定NAT C是由ISP(Internet Service Provider)提供的工业级的NAT设备,NAT C提供将多个下属的用户NAT或用户节点映射到有限的几个公网IP的服务,NAT A和NAT B做为NAT C的内网节点将把用户的家庭网络或内部网络接入NAT C的内网,然后用户的内部网络就可以经由NAT C访问公网了。从这种拓扑结构上来看,只有服务器S与NAT C是真正拥有公网可路由IP地址的设备,而NAT A和NAT B所使用的“公网”IP地址,实际上是由ISP服务提供商设定的(相对于NAT C而言)内网地址(本位的后续部分我把这个由ISP提供的内网地址相对于NAT A和NAT B称之为“伪”公网地址),同理隶属于NAT A与NAT B的客户端,相对与NAT A,NAT B而言,它们处于NAT A,NAT B的内网,以此类推,客户端可以放到到多层NAT设备后面。客户端A和客户端B发起对服务器S的连接的时候,就会依次在NAT A和NAT B上建立向外的session,而NAT A、NAT B要联入公网的时候,会在NAT C上再建立向外的session。现在假定客户端A和B希望通过UDP“打洞”完成两个客户端的p2p直连。最优化的路由策略是客户端A向客户端B的“伪公网”IP上发送数据 包,即ISP服务提供商指定的内网IP,NAT B的“伪”公网endpoint,:55000。由于从服务器S的角度只能观察到真正的公网地址,也就是NAT A,NAT B在NAT C建立的session的真正的公网地址1:62000以及1:62005,所以非常不幸,客户端A与客户 端B是无法通过服务器S知道这些“伪”公网的地址的。而且即使客户端A和B通过某种手段可以得到NAT A和NAT B的“伪”公网地址,我们仍然不建议采用上述的“最优化”的打洞方式,这是因为这些地址是由ISP服务提供商提供的或许会存在与客户端本身所在的内网地址 重复的可能性。(例如:NAT A的内网的IP地址域恰好与NAT A在NAT C的“伪”公网IP地址域重复,这样就会导致打洞数据包无法发出的问题)因此客户端别无选择,只能使用由公网服务器S观察到的A,B的公网endpoint进行“打洞”操作,用于“打洞”的数据包将由NAT C进行转发,这里NAT C是否支持“发夹”转换或“环路”转换非常重要,否则数据包将无法由NAT C转发给NAT A和NAT B,进而无法到达客户端A和B。当客户端A向客户端B的公网endpoint(1:62005)发送UDP数据包的时候,NAT A首先把数据包的源endpoint由A的内网endpoint(:4321)转换为“伪”公网endpoint(: 45000),现在数据包到了NAT C,NAT C应该可以识别出来该数据包是要发往自身转换过的公网endpoint,如果NAT C可以给出“合理”响应的话,NAT C将把该数据包的源endpoint改为1:62000,目的endpoint改为:55000,即NAT B的“伪”公网endpoint,NAT B最后会将收到的数据包发往客户端B。同样,由B发往A的数据包也会经过类似的过程。也有很多NAT设备不支持类似这样的“发夹”转换,但是已经有越来越 多的NAT设备生产厂商开始加入对该转换的支持。3.3 UDP在空闲状态下的超时问题由于UDP转换协议提供的“洞”不是绝对可靠的,多数NAT设备内部都有一个UDP转换的空闲状态计时器,如果在一段时间内没有UDP数据通 信,NAT设备会关掉由“打洞”操作打出来的“洞”,做为应用程序来讲如果想要做到与设备无关,就最好在穿越NAT的以后设定一个穿越的有效期。很遗憾目 前没有标准有效期,这个有效期与NAT设备内部的配置有关,最短的只有20秒左右。在这个有效期内,即使没有p2p数据包需要传输,应用程序为了维持该 “洞”可以正常工作,也必须向对方发送“打洞”维持包。这个维持包是需要双方应用都发送的,只有一方发送不会维持另一方的session正常工作。除了频 繁发送“打洞”维持包以外,还有一个方法就是在当前的“洞”有效期过期之前,p2p客户端双方重新“打洞”,丢弃原有的“洞”,这也不失为一个有效的方 法。4:TCP打洞方式关于TCP打洞技术建立穿越NAT设备的p2p的TCP连接只比UDP复杂一点点,TCP协议的“打洞”从协议层来看是与UDP的“打洞”过程非常相似 的。尽管如此,基于TCP协议的打洞至今为止还没有被很好的理解,这也造成了对其提供支持的NAT设备不是很多。在NAT设备支持的前提下,基于TCP的 “打洞”技术实际上与基于UDP的“打洞”技术一样快捷、可靠。实际上,只要NAT设备支持的话,基于TCP的p2p技术的健壮性将比基于UDP的技术的 更强一些,因为TCP协议的状态机给出了一种标准的方法来精确的获取某个TCP session的生命期,而UDP协议则无法做到这一点。4.1套接字和TCP端口的重用实现基于TCP协议的p2p“打洞”过程中,最主要的问题不是来自于TCP协议,而是来自于应用程序的API接口。这是由 于标准的伯克利(Berkeley)套接字的API是围绕着构建客户端/服务器程序而设计的,API允许TCP流套接字通过调用connect()函数来 建立向外的连接,或者通过listen()和accept函数接受来自外部的连接,但是,API不提供类似UDP那样的,同一个端口既可以向外连接,又能 够接受来自外部的连接。而且更糟的是,TCP的套接字通常仅允许建立1对1的响应,即应用程序在将一个套接字绑定到本地的一个端口以后,任何试图将第二个 套接字绑定到该端口的操作都会失败。为了让TCP“打洞”能够顺利工作,我们需要使用一个本地的TCP端口来监听来自外部的TCP连接,同时建立多个向外 的TCP连接。幸运的是,所有的主流操作系统都能够支持特殊的TCP套接字参数,通常叫做“SO_REUSEADDR”,该参数允许应用程序将多个套接字 绑定到本地的一个endpoint(只要所有要绑定的套接字都设置了SO_REUSEADDR参数即可)。BSD系统引入了SO_REUSEPORT参 数,该参数用于区分端口重用还是地址重用,在这样的系统里面,上述所有的参数必须都设置才行。4.2 打开p2p的TCP流假定客户端A希望建立与B的TCP连接。我们像通常一样假定A和B已经与公网上的已知服务器S建立了TCP连接。服务器记录下来每个 联入的客户端的公网和内网的endpoints,如同为UDP服务的时候一样。从协议层来看,TCP“打洞”与UDP“打洞”是几乎完全相同的过程。1、 客户端A使用其与服务器S的连接向服务器发送请求,要求服务器S协助其连接客户端B。2、S将B的公网和内网的TCP endpoint返回给A,同时,S将A的公网和内网的endpoint发送给B。3、客户端A和B使用连接S的端口异步地发起向对方的公网、内网 endpoint的TCP连接,同时监听各自的本地TCP端口是否有外部的连接联入。4、A和B开始等待向外的连接是否成功,检查是否有新连接联入。如果 向外的连接由于某种网络错误而失败,如:“连接被重置”或者“节点无法访问”,客户端只需要延迟一小段时间(例如延迟一秒钟),然后重新发起连接即可,延 迟的时间和重复连接的次数可以由应用程序编写者来确定。5、TCP连接建立起来以后,客户端之间应该开始鉴权操作,确保目前联入的连接就是所希望的连接。 如果鉴权失败,客户端将关闭连接,并且继续等待新的连接联入。客户端通常采用“先入为主”的策略,只接受第一个通过鉴权操作的客户端,然后将进入p2p通 信过程不再继续等待是否有新的连接联入。4.2.1与UDP打洞的区别与UDP 不同的是,使用UDP协议的每个客户端只需要一个套接字即可完成与服务器S通信,并同时与多个p2p客户端通信的任务,而TCP客户端必须处理多个套接字 绑定到同一个本地TCP端口的问题,如上图所示。现在来看更加实际的一种情景,A与B分别位于不同的NAT设备后面,如上图所示,并且假定图中的端口号是 TCP协议的端口号,而不是UDP的端口号。图中向外的连接代表A和B向对方的内网endpoint发起的连接,这些连接或许会失败或者无法连接到对方。 如同使用UDP协议进行“打洞”操作遇到的问题一样,TCP的“打洞”操作也会遇到内网的IP与“伪”公网IP重复造成连接失败或者错误连接之类的问题。 客户端向彼此公网endpoint发起连接的操作,会使得各自的NAT设备打开新的“洞”允许A与B的TCP数据通过。如果NAT设备支持TCP“打洞” 操作的话,一个在客户端之间的基于TCP协议的流通道就会自动建立起来。如果A向B发送的第一个SYN包发到了B的NAT设备,而B在此前没有向A发送 SYN包,B的NAT设备会丢弃这个包,这会引起A的“连接失败”或“无法连接”问题。而此时,由于A已经向B发送过SYN包,B发往A的SYN包将被看 作是由A发往B的包的回应的一部分,所以B发往A的SYN包会顺利地通过A的NAT设备,到达A,从而建立起A与B的p2p连接。4.3 从应用程序的角度来看TCP“打洞”从应用程序的角度来看,在进行TCP“打洞”的时候都发生了什么呢?假定A首先向B发出SYN包,该包发往B的公网 endpoint,并且被B的NAT设备丢弃,但是B发往A的公网endpoint的SYN包则通过A的NAT到达了A,然后,会发生以下的两种结果中的 一种,具体是哪一种取决于操作系统对TCP协议的实现:(1)A的TCP实现会发现收到的SYN包就是其发起连接并希望联入的B的SYN包,通俗一点来说 就是“说曹操,曹操到”的意思,本来A要去找B,结果B自己找上门来了。A的TCP协议栈因此会把B做为A向B发起连接connect的一部分,并认为连 接已经成功。程序A调用的异步connect()函数将成功返回,A的listen()等待从外部联入的函数将没有任何反映。此时,B联入A的操作在A程 序的内部被理解为A联入B连接成功,并且A开始使用这个连接与B开始p2p通信。由于收到的SYN包中不包含A需要的ACK数据,因此,A的TCP将用 SYN-ACK包回应B的公网endpoint,并且将使用先前A发向B的SYN包一样的序列号。一旦B的TCP收到由A发来的SYN-ACK包,则把自 己的ACK包发给A,然后两端建立起TCP连接。简单的说,第一种,就是即使A发往B的SYN包被B的NAT丢弃了,但是由于B发往A的包到达了A。结果 是,A认为自己连接成功了,B也认为自己连接成功了,不管是谁成功了,总之连接是已经建立起来了。(2)另外一种结果是,A的TCP实现没有像(1)中所 讲的那么“智能”,它没有发现现在联入的B就是自己希望联入的。就好比在机场接人,明明遇到了自己想要接的人却不认识,误认为是其它的人,安排别人给接走 了,后来才知道是自己错过了机会,但是无论如何,人已经接到了任务已经完成了。然后,A通过常规的listen()函数和accept()函数得到与B的 连接,而由A发起的向B的公网endpoint的连接会以失败告终。尽管A向B的连接失败,A仍然得到了B发起的向A的连接,等效于A与B之间已经联通, 不管中间过程如何,A与B已经连接起来了,结果是A和B的基于TCP协议的p2p连接已经建立起来了。第一种结果适用于基于BSD的操作系统对于TCP的 实现,而第二种结果更加普遍一些,多数linux和windows系统都会按照第二种结果来处理。5:基于STUN方式的NAT穿越 STUN的全称是Simple Traversal of UDP Through Network Address Translators,即UDP对NAT的简单穿越方式。 应用程序(即STUN CLIENT)向NAT外的STUN SERVER通过UDP发送请求STUN 消息,STUN SERVER收到请求消息,产生响应消息,响应消息中携带请求消息的源端口,即STUN CLIENT在NAT上对应的外部端口。然后响应消息通过NAT发送给STUN CLIENT,STUN CLIENT通过响应消息体中的内容得知其NAT上的外部地址,并将其填入以后呼叫协议的UDP负载中,告知对端,本端的RTP接收地址和端口号为NAT 外部的地址和端口号。由于通过STUN协议已在NAT上预先建立媒体流的NAT映射表项,故媒体流可顺利穿越NAT. 在典型的运用STUN进行NAT穿透的场景中, STUN客户端首先向位于公网上的STUN服务器 发送Binding Request消息,STUN服务器接收到请求消息后识别出经过NAT转换后的公网地 址:12345,将其附加在Binding Response消息中返回给客户端。客户端得到这个地址 后用它替换SDP中的私网地址与终端B完成媒体协商。使用STUN进行NAT穿透对应用的要 求是必须使用同样的端口与STUN服务器交互和进行应用层通讯,比如当希望使用端口 必须同样使用37000端口与STUN服务器通讯, 否则从STUN 37000进行RTP包的NAT穿透时, 服务器获得的NAT映射后的地址一般与实际地址时不一样的。另一个要求是STUN客户端与 服务器端的通讯和应用使用获得的NAT映射地址进行应用层通讯在时间上必须有连贯性, 这源于NAT设备建立的绑定有生存时间,当原绑定消亡后,NAT设备为同一个私网地址建 立的新绑定往往不同,因此转换后的公网地址是不同的。 STUN协议最大的优点是无需现有NAT/FW设备做任何改动。由于实际应用中,已有大量的 NAT/FW,并且这些NAT/FW并不支持VoIP的应用,如果用MIDCOM或NAT/ALG方式来解决此问题,需要替换现有的NAT/FW,这是不 太容易的。而采用STUN方式无需改动NAT/FW,这是其最大优势,同时STUN方式可在多个NAT串联的网络环境中使用,但MIDCOM方式则无法实 现对多级NAT的有效控制。STUN的局限性在于需要VOIP终端支持STUN CLIENT的功能,同时STUN并不适合支持TCP连接的穿越,因此不支持H323.另外STUN方式不支持对防火墙的穿越,不支持对称NAT (Symmetric NAT)类型(在安全性要求较高的企业网中,出口NAT通常是这种类型)穿越。5.1 STUN检测NAT类型说明在RFC3489/STUN1中,基于UDP的NAT穿透技术把主机划分为如下七种NAT类型:UDP Blocked、Open Internet、Symmetric Firewall、Full Cone NAT、Restricted Cone NAT、Port Restricted Cone NAT、Symmetric NAT。具体解释如下:(1)Open Internet:主机具有公网IP,允许主动发起和被动响应两种方式的UDP通信。(2)UDP Blocked:位于防火墙之后,并且防火墙阻止了UDP通信。(3)Symmetric Firewall:主机具有公网IP,但位于防火墙之后,且防火墙阻止了外部主机的主动UDP通信。(4)Full Cone NAT:当内网主机创建一个UDP socket并通过它第一次向外发送UDP数据包时,NAT会为之分配一个固定的公网IP:端口。此后,通过这个socket发送的任何UDP数据包 都是通过这个公网IP:端口发送出去的;同时,任何外部主机都可以使用这个公网IP:端口向该socket发送UDP数据包。即是说,NAT维护 了一个映射表,内网主机的内网IP:端口与公网IP:端口是一一对应的关系。一旦这个映射关系建立起来(内部主机向某一外部主机发送一次数据即 可),任何外部主机就可以直接向NAT内的这台主机发起UDP通信了,此时NAT透明化了。(5)Restricted Cone NAT:当内网主机创建一个UDP socket并通过它第一次向外发送UDP数据包时,NAT会为之分配一个公网IP:端口。此后,通过这个socket向外发送的任何UDP数据包都 是通过这个公网IP:端口发送出去的;而任何收到过从这个socket发送来的数据的外部主机(由IP标识),都可以通过这个公网IP:端口向该 socket发送UDP数据包。即是说,NAT维护了一个内网IP:端口到公网IP:端口的映射,还维护了一个外部主机IP, 公网IP:端口到内网IP:端口的映射。因此,要想外部主机能够主动向该内部主机发起通信,必须先由该内部主机向这个外部发起一次通信。(6)Port Restricted Cone NAT:当内网主机创建一个UDP socket并通过它第一次向外发送UDP数据包时,NAT会为之分配一个公网IP:端口。此后,通过这个socket向外部发送的任何UDP数据包 都是通过这个公网IP:端口发送出去的;一旦外部主机在IP:端口上收到过从这个socket发送来的数据后,都可以通过这个外部主机IP:端 口向该socket发送UDP数据包。即是说,NAT维护了一个从内网IP:端口到公网IP:端口的映射,还维护了一个从外部主机IP:端 口, 公网IP:端口到内网IP:端口的映射。(7)Symmetrict NAT:当内网主机创建一个UDP socket并通过它第一次向外部主机1发送UDP数据包时,NAT为其分配一个公网IP1:端口1,以后内网主机发送给外部主机1的所有UDP数据 包都是通过公网IP1:端口1发送的;当内网主机通过这个socket向外部主机2发送UDP数据包时,NAT为其分配一个公网IP2:端口2, 以后内网主机发送给外部主机2的所有UDP数据包都是通过公网IP2:端口2发送的。公网IP1:端口1和公网IP2:端口2一定不会完全相 同(即要么IP不同,要么端口不同,或者都不同)。这种情况下,外部主机只能在接收到内网主机发来的数据时,才能向内网主机回送数据。5.2 RFC3489/STUN协议过程STUN协议定义了三类测试过程来检测NAT类型,如下所述:Test1:STUN Client通过端口IP-c1:Port-c1向STUN ServerIP-s1:Port-s1发送一个Binding Request(没有设置任何属性)。STUN Server收到该请求后,通过端口IP-s1:Port-s1把它所看到的STUN Client的IP和端口IP-m1,Port-m1作为Binding Response的内容回送给STUN Client。Test1#2:STUN Client通过端口IP-c1:Port-c1向STUN ServerIP-s2:Port-s2发送一个Binding Request(没有设置任何属性)。STUN Server收到该请求后,通过端口IP-s2:Port-s2把它所看到的STUN Client的IP和端口IP-m1#2,Port-m1#2作为Binding Response的内容回送给STUN Client。Test2:STUN Client通过端口IP-c1:Port-c1向STUN ServerIP-s1:Port-s1发送一个Binding Request(设置了Change IP和Change Port属性)。STUN Server收到该请求后,通过端口IP-s2:Port-s2把它所看到的STUN Client的IP和端口IP-m2,Port-m2作为Binding Response的内容回送给STUN Client。Test3:STUN Client通过端口IP-c1:Port-c1向STUN ServerIP-s1:Port-s1发送一个Binding Request(设置了Change Port属性)。STUN Server收到该请求后,通过端口IP-s1:Port-s2把它所看到的STUN Client的IP和端口IP-m3,Port-m3作为Binding Response的内容回送给STUN Client。5.2.1 NAT类型检测过程1. 进行Test1。如果STUN Client不能够收到STUN Server的应答(重复多次确认),那么说明该STUN Client是UDP Blocked类型(也有可能是STUN Server不可到达,这里不考虑这种情形);否则,STUN Client把返回的IP-m1,Port-m1和本地的IP-c1:Port-c1进行比较(只需要比较IP即可),如果相同,说明本机直接连 接于公网,否则本机位于NAT之后,但还需要进一步判断具体类型。1.1. 如果本机直接连接于公网,进行Test2。如果STUN Client不能够收到STUN Server的应答(重复多次确认),那么说明该STUN Client是Symmetric Firewall类型;否则,该STUN Client是Open Internet类型。1.2. 如果本机位于NAT之后,进行Test2。如果STUN Client能够收到STUN Server的应答,那么说明该STUN Client是Full Cone NAT;否则,需要进一步进行测试。1.2.1. 进行Test1#2。STUN Client比较IP-m1和IP-m1#2是否相同,如果不相同,那么说明该STUN Client是Symmetric NAT类型;否则,需要进一步进行测试。 进行Test3。如果STUN Client能够收到STUN Server的应答,那么说明该STUN Client是Restricted Cone NAT类型;否则,该STUN Client是Port Restricted Cone NAT类型。一些说明:只需要进行Test2,即可判断出是否为Open Internet或Full Cone Nat类型。5.3网上一些可用STUN Server网上一些可用STUN Server(注意:STUN协议指定默认端口为3478)(这个STUN Server的实现好像有问题,测试结果与前面三个不相同)6:基于TURN方式的NAT穿越TURN方式解决NAT问题的思路与STUN相似,也是私网中的VOIP终端通过某种机制预先得公网上的服务地址(STUN方式得到的地址为出口 NAT上外部地址,TURN方式得到地址为TURN Server上的公网地址),然后在报文净载中所要求的地址信息就直接填写该公网地址。TURN的全称为Traversal Using Relay NAT,即通过Relay方式穿越NAT.TURN应用模型通过分配TURN Server的地址和端口作为私网中VOIP终端对外的接受地址和端口,即私网终端发出的报文都要经过TURN Server进行Relay转发,这种方式除了具有STUN方式的优点外,还解决了STUN应用无法穿透对称NAT(SymmetricNAT)以及类 似的Firewall设备的缺陷,同时TURN支持基于TCP的应用,如H323协议。此外TURN Server控制分配地址和端口,能分配RTP/RTCP地址对(RTCP端口号为RTP端口号加1)作为私网终端用户的接受地址,避免了STUN方式中 出口NAT对RTP/RTCP地址端口号的任意分配,使得客户端无法收到对端发来的RTCP报文(对端发RTCP报文时,目的端口号缺省按RTP端口号加 1发送)。TURN的局限性在于需要VOIP终端支持TURN Client,这一点同STUN一样对网络终端有要求。此外,所有报文都必须经过TURN Server转发,增大了包的延迟和丢包的可能性。TURN解决NAT穿透的思路与STUN类似, 都是通过修改应用层中的私网地址达到NAT穿透。与STUN不同的是,TURN是通过两方通讯的“中间人”的方式实现穿透,在这种方式下, 要进行通讯的两方分别与位于公网上的TURN服务
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 高级社工考试题库及答案
- 2025年国机数字科技有限公司社会招聘笔试参考题库附带答案详解
- 2025年锅炉水处理作业G3证理论考试笔试试题含答案
- 2025年心理咨询兼职培训师合同协议
- 海绵厂入职考试题及答案
- 数字八字考试题库及答案
- 印象形成考试题库及答案
- 全自动衣物清洗与烘干设备采购合同
- 衢州国企笔试试题及答案
- 2025年《宪法》知识竞赛测试题及答案(共50题)
- 油田井下作业案例课件
- 项目管理范围管理及计划分解模板
- 2025秋教科版(2024)小学科学二年级上册(全册)课时练习及答案(附目录)
- 2025年中国工商银行校园招聘考试题库历年考试真题及答案
- 挺身式跳远技术
- 2025年香港销售合同范本
- 2024河北工勤人员技师考试汽车驾驶员自测试题及答案-河北职业
- 国有企业财会监督体系构建的路径选择与机制创新
- GB/T 14188-2025气相防锈包装材料选用通则
- 2024镇江市高等专科学校辅导员招聘笔试真题
- 四川省中小学教育技术装备标准 (试行)
评论
0/150
提交评论