首页 > 编程知识 正文

udp穿透库(udp过nat)

时间:2023-05-03 10:56:19 阅读:97421 作者:3552

一:基本术语

防火墙

防火墙限制私有网络和公共网络之间的通信。它主要丢弃(防火墙)认为未经授权的数据包。防火墙只检查数据包的数据,不修改数据包中的IP地址和TCP/UDP端口信息。

网络地址转换

当数据包通过时,网络地址转换器不仅检查数据包信息,还会修改数据包报头中的IP地址和端口信息。这样NAT后面的机器就可以共享几个唯一的公共IP地址(通常是一个)。网络地址转换器主要有两种类型。

P2P应用

P2P应用是指基于现有的公共服务器建立端到端的会话通信,并分别使用自己的私有地址或公共地址(或两者兼有)。

P2P防火墙

P2P防火墙是一种提供防火墙功能,但不执行地址转换的P2P代理。

P2P网络地址转换

P2P-NAT是一种P2P代理,它提供了NAT和防火墙的功能。最简单的P2P代理必须具备锥形NAT的功能才能支持Udp通信,并允许应用程序使用Udp打孔技术建立健壮的P2P连接。

循环转换

当NAT的专网内部机器想通过公有地址访问同一局域网内的机器时,NAT设备相当于做了两次NAT。在数据包到达目标机器之前,它首先将私有地址转换为公共地址,然后将公共地址转换回私有地址。我们把具有上行转换功能的NAT设备称为“环回转换”设备。

00-1010可分为基本NAT和网络地址及端口转换(NAPT)

(1) :基本NAT

基本NAT将专网主机的私有IP地址转换为公网IP地址,但不转换TCP/UDP端口信息。当网络地址转换有许多公共地址时,通常使用基本网络地址转换。它将公共IP地址与内部主机绑定,以便外部主机可以使用公共IP地址访问内部主机。(其实只是转换IP,192.168.0.23-210.42.106.35,不同于将IP地址直接设置为公共IP,特别是对于企业来说,外部信息只能通过统一的防火墙到达内部,而内部主机可以使用公共IP)

(2) :网络地址和端口转换(NAPT)

这是最常见的情况。网络地址/端口转换器检查和修改数据包的IP地址和TCP/UDP端口信息,以便更多的内部主机可以同时使用公共IP地址。

有关NAT分类和术语的更多信息,请参考[RFC1631]和[RFC2993]和[RFC2663]。此外,[RFC2663]给出了更多关于NAPT的分类和术语的定义。当内联网主机通过NAT打开“传出”TCP或UDP会话时,NAPT为该会话分配一个公共IP和端口,用于接收来自外部网络的响应数据包,并在转换后通知内联网主机。其效果是,NAPT在[私有IP:私有端口]和[公共IP:公共端口]之间建立了端口绑定。

端口绑定指定NAPT将在此会话期间执行地址转换任务。中间有这样一个问题。如果一个P2P应用程序同时从内部网络中的一个[私有IP地址3360端口]对向不同的外部主机发出多个会话,那么NAT会做什么?这个可以分为锥形NAT (CONE NAT)和对称NAT (SYMMTRIC NAT)来考虑:

A.锥形NAT

(为什么叫锥度?请看下图。终端和外部服务器都通过NAT分配的这个绑定地址对传输信息,就像漏斗一样,过滤和传输信息)

当建立了[私有IP:端口]-[公共IP 3360端口]端口绑定时,对于来自同一[私有IP 3360端口]的会话,锥形NAT服务器允许发起会话的应用程序重用该端口绑定,直到会话结束(端口绑定)。

例如,假设客户端A(其IP地址信息如上图所示)通过锥形NAT同时发起两个传出连接,并使用相同的内部端口(10.0.0.1:1234)连接到公共网络中的两个不同服务器,即S1和S2。Cone NAT只为这两个会话分配一个公共IP和端口(155.99.25.11:62000),通过地址转换可以保证客户端使用的端口的“身份”(即该客户端只使用该端口)。然而,基本NAT和防火墙不能修改被传递数据包的端口号,它们可以被视为锥形NAT的简化版本。

进一步的分析可以将cone NAT分为受限cone NAT(受限cone NAT)和端口受限CONE NAT(端口受限CONE NAT)。以下是对:分为全双工锥形NAT (FULL CONE NAT)的详细讨论。

1.全双工锥形网络地址转换

当内部主机发出“传出”连接会话时,它将创建一个公共/专用网络地址。一旦创建了这个地址对,全双工锥形NAT将接收从任何外部端口到这个公共端口地址的后续通信。因此,全双工锥形网络地址转换有时被称为“混合”网络地址转换。

2.受限圆锥网络地址转换

受限锥形网络地址转换将过滤传入的数据包。当内部主机发出“传出”会话时,NAT会记录该外部主机的IP地址信息。因此,只有这些记录的外部IP地址才能将信息传递到NAT中。受限锥形网络地址转换有效地完善了防火墙的包过滤原理,即只有那些已知的外部地址才能被赋予进入网络地址转换的信息。

3.端口受限的锥形NAT

端口受限锥形

NAT,与受限制的锥形NAT不同的是:它同时记录了外部主机的IP地址和端口信息,端口受限制的锥形NAT给内部节点提供了同一级别的保护,在维持端口“同一性”过程中,将会丢弃对称NAT传回的信息。

B.对称NAT

对称NAT,与Cone NAT是大不相同的,并不对会话进行端口绑定,而是分配一个全新的公网端口 给每一个新的会话。

还是上面那个例子:如果 Client A (10.0.0.1:1234)同时发起两个 "外出" 会话,分别发往S1和S2。对称Nat会分配公共地址155.99.25.11:62000给Session1,然后分配另一个不同的公共地址155.99.25.11:62001给Session2。对称Nat能够区别两个不同的会话并进行地址转换,因为在 Session1 和 Session2中的外部地址是不同的,正是因为这样,Client端的应用程序就迷失在这个地址转换边界线了,因为这个应用程序每发出一个会话都会使用一个新的端口,无法保障只使用同一个端口了。

在TCP和UDP通信中,(到底是使用同一个端口,还是分配不同的端口给同一个应用程序),锥形NAT和对称NAT各有各的理由。当然锥形NAT在根据如何公平地将NAT接受的连接直达一个已创建的地址对上有更多的分类。这个分类一般应用在Udp通信(而不是Tcp通信上),因为NATs和防火墙阻止了试图无条件传入的TCP连接,除非明确设置NAT不这样做。

三:NAT对session的处理

以下分析NAPT是依据什么策略来判断是否要为一个请求发出的UDP数据包建立Session的.主要有一下几个策略:

A. 源地址(内网IP地址)不同,忽略其它因素, 在NAPT上肯定对应不同的Session

B. 源地址(内网IP地址)相同,源端口不同,忽略其它的因素,则在NAPT上也肯定对应不同的Session

C. 源地址(内网IP地址)相同,源端口相同,目的地址(公网IP地址)相同,目的端口不同,则在NAPT上肯定对应同一个Session

D. 源地址(内网IP地址)相同,源端口相同,目的地址(公网IP地址)不同,忽略目的端口,则在NAPT上是如何处理Session的呢?

A,B,C三种情况的都是比较简单的,可以很容易的实现.而D的情况就比较复杂了.所以D情况才是我们要重点关心和讨论的问题。

四:完全解决方案

以下针对四种SESSION与四种NAT的完全解决方案,为了方便将使用以下缩写形式:

C代表 CONE NAT

S代表SYMMETRIC NAT,

FC代表 FULL CONE NAT,

RC代表 RESTRICT CONE NAT,

PC 代表 PORT RESTRICT CONE NAT.

首先依据CLIENT (客户)端在NAT后 的个数不同可以分为两大类:

TYPE ONE :一个在NAT后 + 一个在公网中.

这种情况下可以分为两大类:

A. S VS 公网:此种情况下,由于公网的地址在一个SESSION内是不变的,所以可以打洞是可以成功的.

B. C VS 公网: 与上面类似,这种情口下打洞是可以成功的.

TYPE TWO:两个客户都在NAT后面.

这种情况下也可以细分为两大类:

A. 其中一个NAT 是 S(SYMMETRIC NAT) 型的,既:S VS C或者是S VS S .

下面论证这种情口下按照常规打洞是行不通的,在常规打洞中,所有的客户首先登陆到一个服务器上去.服务器记录下每个客户的[公网IP:端口],然后在打洞过程中就使用这个记录的值,然而对于S型的NAT来说,它并不绑定[私网IP:端口]和[公网IP:端口]的映射.所以在不同的SESSION中,NAT将会重新分配一对[公网IP:端口].这样一来对于S型的NAT来说打洞的[公网IP:端口]与登记在服务器上的[公网IP:端口]是不同的.而且也没有办法将打洞的[公网IP:端口]通知到另一个位于NAT下的客户端, 所以打洞是不会成功的.然而如果另一个客户端是在公网时,打洞是可以的.前面已经论证了这种情况.

这种情况下的解决方案是只能通过端口预测来进行打洞,具体解决方法如下:例如(以两个都是S型的为例) 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的双向连接就被打通了。其结果如下图所示:

明显的,有许多因素会导致这个方法失败:如果这个预言的新端口(62001和31001) 恰好已经被一个不相关的会话所使用,那么NAT就会跳过这个端口号,这个连接就会宣告失败;如果两个NAT有时或者总是不按照顺序来生成新的端口号,那么这个方法也是行不通的。

如果隐藏在NATA后的一个不同的客户端X(或者在NAT B后)打开了一个新的“外出”UDP 连接,并且无论这个连接的目的如何;只要这个动作发生在客户端A 建立了与服务器S的连接之后,客户端A 与 客户端B 建立连接之前;那么这个无关的客户端X 就会趁人不备地“偷” 到这个我们渴望分配的端口。所以,这个方法变得如此脆弱而且不堪一击,只要任何一个NAT方包含以上碰到的问题,这个方法都不会奏效。

在处于 cone NAT 系列的网络环境中这个方法还是实用的;如果有一方为 cone NAT 而另外一方为 symmetric NAT,那么应用程序就应该预先发现另外一方的 NAT 是什么类型,再做出正确的行为来处理通信,这样就增大了算法的复杂度,并且降低了在真实网络环境中的普适性。

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

因此,并不推荐使用这个方法来写新的P2P应用程序,这也是历史的经验和教训!

B. 两个都是CONE NAT型的.

这种情况下可以分为六大类型:

A: FC + FC

B: FC + RC

C: FC + PC

D: PC + RC

E: PC + PC

F: RC + RC

虽然有这么多种情况,但是由于CONE NAT 的特性,所以还是很好办的,因为对于CONE NAT 来说,在同一个SESSION中它会绑定一对[私网IP:端口]和[公网IP:端口]的映射,所以它们打洞用的[公网IP:端口]与登记在服务器上的[公网IP:端口]是一致的,所以打洞是可以行的通的.

综上所述,就已经完全的概括了所有类型的NAT之间的可能的通信情况了.并且都提供了可行的解决方案.

五:对前一阶段的总结

1.前一阶段使用的打洞方法是有缺陷的,它只适应于两个都是FULL CONE NAT的类型的CLIENT(客户端).以下论证它不适应于两个都是CONE NAT的类型中的

B: FC + RC

C: FC + PC

D: PC + RC

E: PC + PC

F: RC + RC

这五种情况.

因为对于受限的NAT它登记了外出包的[IP地址&端口],它仅仅接受这些已登记地址发过来的包,所以它们报告服务器的端口只能接受来自服务器的包.不能接受来自另一客户端的包.所以前一阶段的打洞方法是不可行的.

六: 存在的问题

按照理论.NAT将在一定时间后关闭UDP的一个映射,所以为了保持与服务器能够一直通信,服务器必须要发送UDP心跳包,来保持映射不被关闭.这就需要一个合适的时间值.

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。