NAT与NAT穿透(二)

5. NAT穿透

5.1 转发

最可靠但又是最低效的点对点通信方法,莫过于将p2p网络通信看作一个C/S结构,通过服务器来转发信息.如下图,两个客户端A和B,均与服务器S初始化了一个TCP或UDP连接,服务器S具有公网固定IP地址,两个客户端分布在不同的私网中,这样,他们各自的NAT代理服务器将不允许他们进行直连.

Server S

|

|

+----------------------+----------------------+

|                                                           |

NAT A                                                 NAT B

|                                                           |

|                                                           |

Client A                                              Client B

取而代之的方式是,两个客户端可以把服务器S当作信使来转发消息.比如,为了将消息发送到B,A先发送一条信息给服务器S,服务器S再利用初始化时已经建立的连接,将信息转发给B.

这个方法的优势是:它适合于任何NAT包括Symmetric NAT.但是它的劣势也很明显:它将全面依赖并消耗服务器的资源和网络带宽.名为 TURN 的协议定义了一个利用转发技术进行可靠通信的模型.

5.2 反向连接

这里介绍第二种技术,但是它只能在通信的两端只有一端处于NAT之后的情况下.举例来说,假设客户端A处于NAT之后,而客户端B有一个公网IP地址,如下图所示.

Server S

18.181.0.31:1235

|

|

+----------------------+----------------------+

|                                                           |

NAT A                                                     |

155.99.25.11:62000                                    |

|                                                           |

|                                                           |

Client A                                              Client B

10.0.0.1:1234                               138.76.29.7:1234

现在我们假设客户端B将会与客户端A初始化一个端对端连接会话.B将首先试图连接A的一个地址---客户端A认为是它自己的地址10.0.0.1:1234或者是从服务器S观察到的地址155.99.25.11:62000.然而不论是连接哪一个,都不可能成功.第一种情况:试图直接连到10.0.0.1肯定会失败,因为10.0.0.1根本就不是一个可以在公网上路由的IP地址;第二种情况,从B传来的请求将能够到达端口NAT A的端口62000,但NAT A却会拒绝这个连接请求,因为只有外出的连接才允许进入.    在所有的尝试都失败之后,客户端B就只能通过服务器S来请求A做一个"反向"连接到客户端B,客户端A将打开一个与客户端B通讯的连接(在B的公网IP地址和端口号上).NAT
A允许这个连接通过,因为这个连接起源于NAT A的内部,并且同时客户端B能够受这个连接因为B并不位于NAT之后.

这个方法的优势是:它也适合于任何NAT包括Symmetric NAT.它的主要限制在于,只能有一端位于NAT之后.

5.3 UDP打洞

第三种技术,也是这篇文章主要要介绍的,就是非常有名的"UDP打洞技术".这里将考虑两种典型场景,来介绍连接的双方应用程序如何按照计划的进行通信的,第一种场景,我们假设两个客户端都处于不同的NAT之后;第二种场景,我们假设两个客户端处于同一个NAT之后,但是它们彼此都不知道(他们在同一个NAT中).

5.3.1 处于不同NAT之后的客户端通信

我们假设 Client A和Client B都拥有自己的私有IP地址,并且都处在不同的NAT之后,端对端的程序运行于 CLIENT A,CLIENT B,S之间,并且它们都开放了UDP端口1234. CLIENT A和CLIENT B首先分别与S建立通信会话,这时NAT A把它自己的UDP端口62000分配给CLIENT A与S的会话,NAT B也把自己的UDP端口31000分配给CLIENT B与S的会话.如下图所示:

Server S

18.181.0.31:1234

|

|

+----------------------+----------------------+

|                                                           |

NAT A                                                 NAT B

155.99.25.11:62000                            138.76.29.7:31000

|                                                           |

|                                                           |

Client A                                              Client B

10.0.0.1:1234                                 10.1.1.3:1234

假如这个时候 CLIENT A 想与 CLIENT B建立一条UDP通信直连,如果 CLIENT A只是简单的发送一个UDP信息到CLIENT B的公网地址

138.76.29.7:31000的话,NAT B会不加考虑的将这个信息丢弃(除非NAT B是一个 full cone NAT),因为这个UDP信息中所包含的地址信息,与CLIENT B和服务器S建立连接时存储在NAT B中的服务器S的地址信息不符.同样的,CLIENT B如果做同样的事情,发送的UDP信息也会被NAT A丢弃.

假如 CLIENT A 开始发送一个UDP信息到CLIENT B的公网地址上,与此同时,他又通过S中转发送了一个邀请信息给CLIENT B,请求CLIENT B也给CLIENT A发送一个UDP信息到 CLIENT A的公网地址上.这时CLIENT A向CLIENT B的公网IP(138.76.29.7:31000)发送的信息导致 NAT A 打开一个处于CLIENT A的私有地址和CLIENT B的公网地址之间的新的通信会话,与此同时NAT B也打开了一个处于CLIENT B的私有地址和CLIENT A的公网地址(155.99.25.11:62000)之间的新的通信会话.一旦这个新的UDP会话各自向对方打开了,CLIENT
A和CLIENT B之间就可以直接通信,而无需S来牵线搭桥了.这就是所谓的打洞技术.

一旦这种处于NAT之后的端对端的直连建立之后,连接的双方可以轮流担任对方的"媒人",把对方介绍给其他的客户端,这样就极大的降低了服务器S的工作量.

5.3.2 处于相同NAT之后的客户端通信

我们假设 Client A和Client B都拥有自己的私有IP地址,并且都处在相同的NAT之后,端对端的程序运行于 CLIENT A,CLIENT B,S之间,

CLIENT A和CLIENT B分别与S建立通信会话,经过NAT转换后,A的公网端口被映射为62000,B的公网端口映射为62001.如下图所示:

Server S

18.181.0.31:1234

|

|

NAT

A-S 155.99.25.11:62000

B-S 155.99.25.11:62001

|

+----------------------+----------------------+

|                                                           |

Client A                                              Client B

10.0.0.1:1234                                 10.1.1.3:1234

根据前面介绍的"打洞"技术,CLIENT A将发送一个UDP信息到CLIENT B的公网地址上,数据包源端为(10.0.0.1:124),目的端为(155.99.25.11:62001).该数据包能否被B收到,取决于当前的NAT是否支持"发夹"转换(hairpin转换,也就是同一台设备不同端口之间的UDP数据包能否到达).

首先,支持"发夹"转换的NAT设备还远没有支持"打洞"技术的NAT设备多,其次,即使NAT设备支持"发夹"转换,在这种情况下也应该通过网内端到端实现,而不是将数据包无谓 地经过NAT设备,这是一种对资源的浪费.

5.3.3 一般"打洞"过程

综合上面介绍的客户端处于不同NAT之后和处于同一NAT之后,我们说下一般的"打洞"过程.

1. 打洞技术假定客户端A和B可以与公网内的已知的集中服务器建立UDP连接(可以互发UDP数据包).当一个客户端在S上登陆的时候,服务器记录下该客户端的两个endpoints(IP地址,UDP端口),一个是该客户端确信自己是通过该ip和端口与服务器S进行通信的,另一个是服务器S记录下的由服务器"观察"到的该客户端实际与自己通信所使用的ip和端口.我们可以把前一个endpoint看作是客户端的内网ip和端口,把后一个endpoint看作是客户端的内网ip和端口经过NAT转换后的公网ip和端口.服务器可以从客户端的登陆消息的消息体中得到该客户端的内网endpoint相关信息,可以通过对登陆消息的IP或UDP头得到该客户端的公网endpoint.

2.假设Client A想向B发起连接,于是A向服务器S发送消息,请求S帮助建立与B的UDP连接.这时,S将B的公网和内网的endpoint发给A.可知,A与B通过与S的一次通信就可以知道对方的公网和内网的endpoint.

3.Client A通过B的内网endpoint发送UDP数据包.针对5.3.2节问题的解决方案.如果B和A在同一NAT后,则很快收到响应.如果B和A不在同一NAT后,则超时.

4.Client A通过B的外网endpoint发送UDP数据包.

回到5.3.1节介绍的具体方法.CLIENT A发出UDP包(10.0.0.1:1234,138.76.29.7:31000),经NAT A转换为(155.99.25.11:62000,138.76.29.7:31000),经NAT B转换为(155.99.25.11:62000,10.1.1.3:1234).如果在此数据包到达NAT B前,B发送过UDP包到A的公网endpoint,则NAT B允许此包到达B机.在5.3.2节下,A发出UDP包(10.0.0.1:1234,155.99.25.11:62001),NAT
先转换为(155.99.25.11:62000,155.99.25.11:62001),再转换为(155.99.25.11:62000,10.1.1.3:1234).

5.步骤3,4发送的数据包是为了"打洞",打洞成功后,就进入真正的P2P传输了.

还有一种情况,B和A不在同一NAT后,C和A在同一NAT后,且B和C的内网endpoint一致,这个时候A从S拿到的目的端应该有2个.所以针对3,4步骤取先有回应的目的端不可取,应该先做步骤3,有回应直接到步骤5,没有回应到步骤4.

5.3.4 客户端分别处于多层NAT之后

在有些网络拓扑中就存在多层NAT设备,让我们来看看下图这种情况:

假如 NAT X 是由 Internet服务供应商(ISP)配置的一个大型NAT,它使用少量的公网IP地址来为一些客户群提供服务,NAT A和NAT B则是

为ISP的两个客户群所配置的小一点的独立NAT网关,它们为各自客户群的私人家庭网络提供IP地址.只有Server S和NAT X拥有公网固定IP地址,而NAT A 和 NAT B所拥有的"公网"IP地址对于ISP的寻址域来说则实际上"私有"的.

Server S

18.181.0.31:1234

|

|

NAT X

A-S 155.99.25.11:62000

B-S 155.99.25.11:62001

|

|

+----------------------+----------------------+

|                                                           |

NAT A                                                 NAT B

192.168.1.1:30000                             192.168.1.2:31000

|                                                           |

|                                                           |

Client A                                              Client B

10.0.0.1:1234                                 10.1.1.3:1234

现在让我们假设Client A和Client B想要建立一条端对端 的UDP直连.Client A和 Client B只知道Server S记录的他们真正的公网地址

155.99.25.11:62000和155.99.25.11:62001,而且他们只能通过这个公网地址建立连接,即NAT X必须得支持"loopback translation"(也称hairpin转换)才行.

Client A和 Client B也知道对方内网地址10.0.0.1:1234和10.1.1.3:1234,毫无疑问,通过内网地址是建立不了连接的.Client A和 Client B并不知道对方NAT B和NAT A的地址192.168.1.2:31000和192.168.1.1:30000,即便假设我们通过某种途径得知了这些地址,还是不能够保证这样就能进行通话了,因为这些地址是由ISP的私有寻址域分配的,可能会与私有域所分配的其他无关客户端地址相冲突.

5.3.5 UDP在空闲状态下的超时问题

由于UDP转换协议提供的"洞"不是绝对可靠的,多数NAT设备内部都有一个UDP转换的空闲状态计时器,如果在一段时间内没有UDP数据通信,NAT设备会关掉由"打洞"操作打出来的"洞",做为应用程序来讲如果想要做到与设备无关,就最好在穿越NAT的以后设定一个穿越的有效期.很遗憾目前没有标准有效期,这个有效期与NAT设备内部的配置有关,最短的只有20秒左右.在这个有效期内,即使没有p2p数据包需要传输,应用程序为了维持该"洞"可以正常工作,也必须向对方发送"打洞"维持包.这个维持包是需要双方应用都发送的,只有一方发送不会维持另一方的session正常工作.除了频繁发送"打洞"维持包以外,还有一个方法就是在当前的"洞"有效期过期之前,p2p客户端双方重新"打洞",丢弃原有的"洞",这也不失为一个有效的方法.

5.4 . UPD端口号预言

在使用"UDP打洞技术"时有一点必须要注意:它只能在双方的NAT都是cone NAT时才能正常工作.这些NAT在使用时保持着端口的

绑定----[私有IP,私有UDP端口]对和[公网IP,公网UDP端口]对的一一对应.

如果像 symmetricNAT那样给每个新的会话都分配一个新的公网端口,那么UDP应用程序想要与其他外部客户端进行通话,就无法重复使用已经建立好的通信转换.

让我们来考虑这样一种情况,有两个客户端A和B,他们都藏在不同的Symmetric NAT后面,他们都开放了一个UDP连接给具有固定IP的Server S.如下图:

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的通信会话.通过与服务器S的对话,客户端A和客户端B都相互知道了对方所映射的真实IP和端口.

客户端A发送一条UDP消息到 138.76.29.7:31001(请注意到端口号的增加),同时客户端B发送一条UDP消息到 155.99.25.11:62001.

如果NAT A 和NAT B继续分配端口给新的会话,并且从A-S和B-S的会话时间消耗得并不多的话,那么一条处于客户端A和客户端B之间的双向会话通道就建立了.

客户端A发出的消息送达B导致了NAT A打开了一个新的会话,并且我们希望 NAT A将会指派62001端口给这个新的会话,因为62001是

继62000后,NAT会自动指派给 从服务器S到客户端A之间的新会话的端口号;类似的,客户端B发出的消息送达A导致了NAT B打开了

一个新的会话,并且我们希望 NAT B将会指派31001这个端口给新的会话;如果两个客户端都正确的猜测到了对方新会话被指派的端口号,

那么这个客户端A----客户端B的双向连接就被打通了.其结果如下图所示:

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

明显的,有许多因素会导致这个方法失败:如果这个预言的新端口(62001和31001) 恰好已经被一个不相关的会话所使用,那么NAT就会跳过这个端口号,这个连接就会宣告失败;如果两个NAT有时或者总是不按照顺序来生成新的端口号,那么这个方法也是行不通的.如果隐藏在NAT A后的一个不同的客户端X(或者在NAT B后)打开了一个新的"外出"UDP 连接,并且无论这个连接的目的如何,只要这个动作发生在客户端A建立了与服务器S的连接之后,客户端A与客户端B建立连接之前,那么这个无关的客户端X 就会趁人不备地"偷"到这个我们渴望分配的端口.所以,这个方法变得如此脆弱而且不堪一击,只要任何一个NAT方包含以上碰到的问题,这个方法都不会奏效.

最后,如果P2P的一方处在两级或者两级以上的NAT下面,并且这些NAT接近这个客户端是symmetric的话,端口号预言是无效的.

因此,并不推荐使用这个方法来写新的P2P应用程序.

5.5 同时开放TCP连接

这里有一种方法能够在某种情况下建立一个穿透NAT的端对端TCP直连.我们知道,绝大多数的TCP会话的建立,都是通过一端先发送一个SYN包开始,另一方则回发一个SYN-ACK包的过程.然而,这里确实存在另外一种情况,就是P2P的双方各自同时地发出一个SYN包到对方的公网地址上,然后各自都单独地返回一个ACK响应来建立一个TCP会话.这个过程被称之为"Simultaneous open"(同时开放连接).

如果一个NAT接收到一个来自私有网络外面的TCP SYN包,这个包想发起一个"引入"的TCP连接,一般来说,NAT会拒绝这个连接请求并扔掉这个SYN 包,或者回送一个TCP RST(connection reset,重建连接)包给请求方.但是,有一种情况,当这个接收到的SYN包中的源IP地址和端口,目标IP地址和端口都与NAT登记的一个已经激活的TCP会话中的地址信息相符时,NAT将会放行这个SYN 包,让它进入NAT内部.特别要指出,如果NAT恰好看到一个刚刚发送出去的一个SYN包也和上面接收到的SYN包中的地址信息相符合的话,那么NAT将会认为这个TCP连接已经被激活,并将允许这个方向的SYN包进入NAT内部.

如果Client A和Client B能够彼此正确的预知对方的NAT将会给下一个TCP连接分配的公网TCP端口,并且两个客户端能够同时地发起一个"外出"的TCP连接,并在对方的SYN包到达之前,自己刚发送出去的SYN包都能顺利的穿过自己的NAT的话,一条端对端的TCP连接就成功地建立了.

不幸的是,这个诡计比5.4节所讲的UDP端口预言更容易被粉碎,并且对时间的敏感性的依赖更多.

这个属于TCP穿透,它同样基于NAT对TCP穿透的支持,基本原理和UDP穿透一致.具体实现后面会继续介绍.

时间: 2024-11-24 08:18:36

NAT与NAT穿透(二)的相关文章

(转)NAT与NAT穿透 原理

原文:http://blog.csdn.net/ustcgy/article/details/5655050 5. NAT穿透5.1 转发     最可靠但又是最低效的点对点通信方法,莫过于将p2p网络通信看作一个C/S结构,通过服务器来转发信息.如下图,两个客户端A和B,均与服务器S初始化了一个TCP或UDP连接,服务器S具有公网固定IP地址,两个客户端分布在不同的私网中,这样,他们各自的NAT代理服务器将不允许他们进行直连.                                  

NAT与NAT穿透(一)

1. NAT简介 前面的文章说到了针对IP不足的许多技术,但这些技术基本都不会增加可用的IP地址数.NAT(Network Address Translation)又称"网络地址转换",它是一种把内部私有网络地址翻译成合法网络IP地址的技术,个人认为该技术是解决IP地址不足最有效的方法.它是一个IETF(Internet Engineering Task Force,Internet工程任务组)标准. 简单地说,NAT就是在局域网内部使用私有地址(前面文章说到过每类IP地址都有私有地址

NAT转发实例(二)

如上图所示: 我们需要将内网的两台PC能够访问外网的PC2 但是因为外网也有个路由器 所以我们需要在外网的那台PC上(PC2) 添加个网关(网关地址为与路由器相连的地址) 具体配置如下 Router5的配置如下: Router>en Router#config Configuring from terminal, memory, or network [terminal]? Enter configuration commands, one per line.  End with CNTL/Z.

TCP/UDP端口NAT映射---NAT转发实例(五)

这次我们要做的实验就是将本地的服务器地址映射到外网的端口地址 我们这次用网页显示来确定我们有没有配置成功 这里配置ip什么的就不说了 我们先来看看服务器的HTTP(也就是web服务)有没有开启 这样就是开启的,里面可以自己编写一两句测试的HTML代码. 我们就将里面代码全删了,然后写上hello!word! 然后测试下内网的能不能访问(只要配好了ip地址就能够通过网页访问的) 结果当然是能够显示的 然后我们配置路由器 以下是路由器配置: Router>enRouter#configConfigu

NAT的全然分析及其UDP穿透的全然解决方式

NAT的全然分析及其UDP穿透的全然解决方式 一:基本术语 防火墙 防火墙限制了私网与公网的通信,它主要是将(防火墙)觉得未经授权的的包丢弃,防火墙仅仅是检验包的数据,并不改动数据包中的IP地址和TCP/UDPport信息. 网络地址转换(NAT) 当有数据包通过时,网络地址转换器不仅检查包的信息,还要将包头中的IP地址和port信息进行改动.以使得处于NAT之后的机器共享几个仅有的公网IP地址(一般是一个).网络地址转换器主要有两种类型. P2P应用程序 P2P应用程序是指,在已有的一个公共s

网络 解决外网与内网或内网之间的通信,NAT穿透

在网络编码中会发现程序在局域网中是可以适用的,但是在外网与内网之间和内网与内网之间就不可行.问题就在于NAT.首先介绍下NAT. NAT的作用NAT(Network Address Translator),网络地址转换.顾名思义,它是一种把内部私有网络IP地址翻译成公有网络IP地址的技术,如图5-1所示.NAT是在IP地址日益缺乏的情况下产生的,它的主要目的是使地址能够重用[9].  图5-1 NAT模型  IP地址分为五类:A类,B类,C类,D类,E类(这里不考虑保留的IP地址).A.B.C类

NAT穿透的详细讲解及分析

原文地址:http://bbs.pediy.com/thread-131961.htm 一.什么是NAT?为什么要使用NAT?NAT是将私有地址转换为合法IP地址的技术,通俗的讲就是将内网与内网通信时怎么将内网私有IP地址转换为可在网络中传播的合法IP地址.NAT的出现完美地解决了lP地址不足的问题,而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机.  二.NAT的分类    STUN标准中,根据内部终端的地址(LocalIP:LocalPort)到NAT出口的公网地址(Pub

NAT穿透技术

在现实Internet网络环境中,大多数计算机主机都位于防火墙或NAT之后,只有少部分主机能够直接接入Internet.很多时候,我们希望网络中的两台主机能够直接进行通信,即所谓的P2P通信,而不需要其他公共服务器的中转.由于主机可能位于防火墙或NAT之后,在进行P2P通信之前,我们需要进行检测以确认它们之间能否进行P2P通信以及如何通信.这种技术通常称为NAT穿透(NAT Traversal).最常见的NAT穿透是基于UDP的技术,如RFC3489中定义的STUN协议. STUN,首先在RFC

转发 通过NAT和防火墙特性和TCP穿透的测评(翻译)

转自 http://blog.csdn.net/sjin_1314/article/details/18178329 原文:Characterization and Measurement of TCP Traversal through NATs and Firewalls 原作者:Saikat Guha Paul Francis [摘要]     近些年,标准化社区已经开发出一些UDP穿透NAT/防火墙的技术(也就是,在NAT之后的主机之间建立UDP流).然而,由于TCP连接建立的不对称特点