http://www.cnblogs.com/whyandinside/archive/2010/12/08/1900492.html

http://www.gzsec.com/oldversion/filesys/news_view.asp?newsid=84

NAT的原理
NAT怎么能够节约公网IP地址呢?这是因为它能够让由私有IP构成的局域网内所有的计算机通过一台具有公网IP和NAT功能的计算机进入公网(Internet),比如上网冲浪,这样一个局域网就只需要一个或很少几个公网IP就行了,从而达到了节约公网IP地址的目的。也许你要问了,为什么需要NAT呢?局域网的私有IP计算机不是能够通过网关直接进入公网吗?非也,内网IP的数据包根本就不可能在公网上传播,因为公网上的路由器都是屏蔽掉了这些私网IP的,这是因为私有IP本来就是人为保留出来专供私有网络通信用的(RFC 1597中描述)。从另一个角度说,即使私有数据包能够到达公网目标地址,目标地址的响应包也不可能返回真正的源地址,因为源地址是私有IP,目标发送的响应包一种可能是被目标地址所在的拥有相同网络号的内网接收,一种可能就是这种子网不存在,数据包被抛弃。所以内网数据包在进入公网之前,必须被翻译成公网IP,这就是NAT的功能,而且NAT技术发展到现在,已不仅局限于翻译IP地址,现在实际翻译时,它不光翻译IP地址,还会翻译TCP/UDP端口。由于这个功能,NAT通常都位于网关计算机上,起着一种路由器的作用,为了讲述方便,以后我们就称这台网关计算机为NAT设备。下面就来看看NAT翻译的基本过程(假如局域网192.168.0.0的NAT设备公网IP是218.70.201.185,私有IP是192.168.0.1,现在客户机192.168.0.88要通过NAT设备访问cn.yahoo.com的网页,cn.yahoo.com的IP是202.43.216.55)。
当客户机192.168.0.88通过IE向 http://cn.yahoo.com发出请求时,它发出的数据包含有下面的信息:
源地址和源端口:192.168.0.88:1234
目标地址和目标端口:202.43.216.55:80
当这个数据包到达NAT设备时,它会检测到这个数据包是要发向公网的,所以它会对源IP地址和端口进行修改(翻译),并在映射表中新建IP和端口的映射条目,然后再把修改的数据包转发出去,下面就是修改后数据包的相关信息。
源:218.70.201.185:8999
目标:202.43.216.55:80 (无需变)
当cn..yahoo.com响应时,它会把数据包发给NAT设备,它的数据包含有下面的信息,
源:202.43.216.55:80
目:218.70.201.185:8999
当NAT设备收到响应时,它会检查它的IP地址/端口映射表,并且会找到218.70.201.185:8999与192.168.0.88:1234的映射条目,于是它又修改数据包,然后把数据包转发给192.168.0.88。相关数据包信息如下:
源:202.43.216.55:80
目:192.168.0.88:1234
具体的翻译步骤就如图1所示,其中图1黑线左侧是内网发向公网的翻译过程,右侧则是公网发向内网的翻译过程,从中可以看出,翻译过程也是从上层向下层进行的。

从上面可以看出,最开始发起连接的内网计算机(这里是192.168.0.88)对网关进行NAT翻译是一无所知的,它根本就不知道网关对它的数据包“做了手脚”,上面所讲的可以说是最理想的翻译,这种翻译对IP地址和端口信息只存在于IP首部和TCP/UDP首部的数据包是非常适合的,但恰恰这个世界是复杂的,网络世界也不例外,每种技术都会有它的缺陷,下面就来看看NAT所面临的网络连接问题。

NAT有4种不同的类型

1) Full Cone

这种NAT内部的机器A连接过外网机器C后,NAT会打开一个端口.然后外网的任何发到这个打开的端口的UDP数据报都可以到达A.不管是不是C发过来的.
例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88
A(192.168.8.100:5000) -> NAT(202.100.100.100:8000) -> C(292.88.88.88:2000)
任何发送到 NAT(202.100.100.100:8000)的数据都可以到达A(192.168.8.100:5000)

2) Address Restricted Cone

这种NAT内部的机器A连接过外网的机器C后,NAT打开一个端口.然后C可以用任何端口和A通信.其他的外网机器不行.
例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88
A(192.168.8.100:5000) -> NAT(202.100.100.100 : 8000) -> C(292.88.88.88:2000)
任何从C发送到 NAT(202.100.100.100:8000)的数据都可以到达A(192.168.8.100:5000)

3) Port Restricted Cone

这种NAT内部的机器A连接过外网的机器C后,NAT打开一个端口.然后C可以用原来的端口和A通信.其他的外网机器不行.
例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88
A(192.168.8.100:5000) -> NAT(202.100.100.100 : 8000) -> C(292.88.88.88:2000)
C(202.88.88.88:2000)发送到 NAT(202.100.100.100:8000)的数据都可以到达A(192.168.8.100:5000)

以上三种NAT通称Cone NAT(圆锥形NAT).我们只能用这种NAT进行UDP打洞.

4) Symmetric(对称形)

对于这种NAT。连接不同的外部Server,NAT打开的端口会变化。也就是内部机器A连接外网机器B时,NAT会打开一个端口,连接外网机器C时又会打开另外一个端口。

对于双方都是Port Restricted Cone NAT的时候,则需要利用UDP打洞原理进行“先打洞,然后才能直接通信”。

于Cone NAT.要采用UDP打洞.需要一个公网机器server
C来充当”介绍人”.处于NAT之后的内网的A,B先分别和C通信,打开各自的NAT端口.C这个时候知道A,B的公网IP: Port.
现在A和B想直接连接.比如A给B直接发包,除非B是Full Cone,否则不能通信.反之亦然.
为什么啊?因为对于处于NAT之后的A,B。
如果想A要与外界的D通信,则首先必须要A发包到D,然后A经过NAT设备NA,NA把A的内网地址和端口转换为NA的外网地址和端口。和D通信之后,D
才能经过NA和A通信。也就是说,只能A和外界主动通信,外界不能主动和处于NA之后的A通信。这种包会被NA直接丢弃的。这也就是上面所说的Port
Restricted Cone 的情形啊! A(192.168.8.100:5000) ->
NA(202.100.100.100:8000) -> D(292.88.88.88:2000)但是我们可以这样.
A --- NA --- Server C --- NB --- B

  • A,B 为主机;
  • NA, NB 为NAT设备;
  • Server C为外网的机器;
  1. 如果A想与B通信;
  2. A首先连接 C, C得到A的外网NA的地址和端口;
  3. B也要连接C,C得到B的外网NB的地址和端口;
  4. A告诉C说我要和B通讯;
  5. C通过NB发信息给B,告诉B A的外网NA的地址和端口;
  6. B向NA发数据包(肯定会被NA丢弃,因为NA上并没有 A->NB 的合法session),但是NB上就建立了有B->NA的合法session了;
  7. B发数据包给C,让 C 通知 A,我已经把洞打好了;
  8. A接受到通知后向 B 的外网发NB数据包,这样就不会被丢弃掉了。因为对于NB来说,它看到的是A的外网NA的地址,而通过第6步,B已经让NA成为NB的合法通信对象了。所以当NA发数据包给NB时,NB就会接收并转发给B;
  9. B给A发数据反过来走一遍就可以了。

注意: 路由器和防火墙的UDP打洞的端口有个时间限制的,在一定时间内如果没有数据通讯会自动关闭

STUN

STUN
的全称是Simple Traversal of UDP Through NAT,即UDP对NAT的简单穿越方式。应用程序(即STUN
CLIENT)向NAT外的STUN SERVER通过UDP发送请求STUN 消息询问自身的转换后地址,STUN
SERVER收到请求消息,产生响应消息,响应消息中携带请求消息的源端口,即STUN
CLIENT在NAT上对应的外部端口。然后响应消息通过NAT发送给STUN CLIENT,STUN
CLIENT通过响应消息体中的内容得知其在NAT上对应的外部地址,并且将其填入以后呼叫协议的UDP负载中,告知对端,同时还可以在终端注册时直接注
册这个转换后的公有IP地址,这样就解决了H.323/MGCP/SIP穿越NAT的通信建立问题以及作为被叫时的问题。本端的接收地址和端口号为NAT
外的地址和端口号。由于通过STUN协议已在NAT上预先建立媒体流的NAT映射表项,故媒体流可顺利穿越NAT。
需要注意的是,NAT/PAT
对于地址转换关系是有一定生命期的,某个地址转换后在一段时间内没有被使用将会被清除,当这个业务流再次出现时,将会建立一个新的地址转换关系,这就意味
着STUN的询问过程以及终端的注册过程都需要再执行一遍才能保证通信的正确。解决这个问题一个比较通行的方案是采用某种方式保持NAT/PAT的转换关
系,例如在NAT/PAT生命期内重复注册一次,比如NAT/PAT的生命期是3分钟,那么就将注册重复周期设置为2分钟。

另外STUN server并非指一个专用的服务器,而是指一种功能、一个协议,我们可以在softswitch或者任何一个需要此功能的服务器上内置此协议, 后面代码也包含一个简单的Server实现。


是在NAT采用对称模式(symmetric NAT)工作时,STUN的方案就会出现问题。假如我们在softswitch上提供STUN
server功能,终端A通过STUN可以获得NAT为终端A与softswitch之间通信分配的地址A',并将这个地址注册在softswitch
上,当一个公网上的终端B呼叫终端A时,A'和B通过softswitch完成呼叫建立过程。当B试图向A'发送媒体流时,问题就出现了。因为对称NAT
只允许从softswitch发送数据给地址A',从B发送的媒体流将被丢弃。所以STUN无法应用于工作在对称模式的NAT.

STUN协议最大的优点是无需现有NAT/FW设备做任何改动,同时STUN方式可在多个NAT串联的网络环境中使用. STUN的局限性在于STUN并不适合支持TCP连接的穿越,同时STUN方式不支持对对称NAT(Symmetric NAT).

TURN


种方式又称SPAN(Simple Protocol for Augmenting NATs)方式.
TURN方式解决NAT问题的思路与STUN相似,也是基于私网接入用户通过某种机制预先得到其私有地址对应在公网的地址(STUN方式得到的地址为出口
NAT上的地址,TURN方式得到地址为TURNServer上的地址),然后在报文负载中所描述的地址信息直接填写该公网地址的方式,实际应用原理也是
一样的。
TURN的全称为Traversal Using
RelayNAT,即通过Relay方式穿越NAT,TURN应用模型通过分配TURNServer的地址和端口作为客户端对外的接受地址和端口,即私网
用户发出的报文都要经过TURNServer进行Relay转发,这种方式除了具有STUN方式的优点外,还解决了STUN应用无法穿透对称
NAT(Symmetric
NAT)以及类似的Firewall设备的缺陷,即无论企业网/驻地网出口为哪种类型的NAT/FW,都可以实现NAT的穿透,同时TURN支持基于
TCP的应用,如H323协议。TURN的局限性在于所有报文都必须经过TURNServer转发,增大了包的延迟和丢包的可能性.

ICE

ICE跟STUN和TURN不一样,ICE不是一种协议,而是一个framework,它整合了STUN和TURN。

UPnP

UPnP是若干网络协议的组合,主要用于设备的互联,但是一种叫做Internet Gateway Device (IGD) Protocol的防火墙穿越技术是基于UPnP的。

最新文章

  1. Listener实现单态登陆
  2. 编写可维护的JavaScript代码
  3. Android开发学习---使用Intelij idea 13.1 进行android 开发
  4. 炼数成金(dataguru)IT技能修炼
  5. Asp.net MVC中Html.Partial, RenderPartial, Action,RenderAction 区别和用法
  6. 转载:GridControl使用技巧
  7. POJ 1062 昂贵的聘礼
  8. python 循环设计
  9. list对象排序
  10. App架构经验总结(转)
  11. 在安装软件CAJViewer时出现,“错误1327。无效驱动器:F:
  12. HTML学习二(基础)
  13. vue+uwsgi+nginx部署前后端分离项目
  14. hdu 2859 Phalanx (最大对称子矩阵)
  15. excel函数vloopup使用方法
  16. [python]socket.listen(backlog)中的backlog含义
  17. webpack打包vue项目之后生成的dist文件该怎么启动运行
  18. 阿里云Tengine和Openresty/1.11.2.3 数据对比
  19. DELPHI - How to use opendialog1 for choosing a folder? TOpenDialog, TFileOpenDialog
  20. 禁用gridview,listview回弹或下拉悬停

热门文章

  1. [UEditor]百度编辑器配置总结
  2. Form_Form Builder编译fmb/library/menu方式总结(汇总)
  3. QT之实现程序启动画面
  4. android之datepicker控件用法
  5. python argparse模块解析命令行选项简单使用
  6. .Net调用非托管代码数据类型不一致的问题
  7. 看oracle版本
  8. 20145305 《Java程序设计》第5周学习总结
  9. substring与substr
  10. java生产随机字符串