如图2所示,私有网主机192.168.1.2要访问公共网中的Http服务器166.111.80.200。首先,要创建TCP链接,假设分配的TCP Port是1010,发送了1个IP包(Des=166.111.80.200:80,Src=192.168.1.2:1010),当IP包通过NAT 网关时,NAT会将IP包的源IP转换为NAT的公共IP,同时将源Port转换为NAT动态分配的1个Port。而后,转发到公共网,此时IP包 (Des=166.111.80.200:80,Src=202.204.65.2:2010)已经不含任何私有网IP和Port的信息。因为IP包的源 IP和Port已经被转换成NAT的公共IP和Port,响应的IP包 (Des=202.204.65.2:,Src=2010166.111.80.200:80)将被发送到NAT。这时NAT会将IP包的目的IP转换成 私有网主机的IP,同时将目的Port转换为私有网主机的Port,而后将IP包 (Des=192.168.1.2:1010,Src=166.111.80.200:80)转发到私网。对于通讯双方而言,这种IP地址和Port的转 换是彻底透明的。数据库
NAPT(Network Address Port Translation)即网络端口地址转换,就是将多个内部地址映射为一个合法公网地址,但以不一样的协议端口号与不一样的内部地址相对应。也就是<内部地址+内部端口>与<外部地址+外部端口>之间的转换。NAPT广泛用于接入设备中,它能够将中小型的网络隐藏在一个合法的IP地址后面。服务器
NAPT使得一组主机能够共享惟一的外部地址,当位于内部网络中的主机经过NAT设备向外部主机发起会话请求时,NAT设备就会查询NAT表,看是否有相关会话记录,若是有相关记录,就会将内部IP地址及端口同时进行转换,再转发出去;若是没有相关记录,进行IP地址和端口转换的同时,还会在NAT表增长一条该会话的记录。外部主机接收到数据包后,用接受到的合法公网地址及端口做为目的IP地址及端口来响应,NAT设备接收到外部回来的数据包,再根据NAT表中的记录把目的地址及端口转换成对应的内部IP地址及端口,转发给该内部主机。网络
如下给出了一个实例(如图1-2),NAPT的基本过程与NAT相似,所不一样的是:NAPT中内部端口与内部地址都进行了转换,而NAT中仅仅只对内部地址进行转换。数据结构
图1-2 网络端口地址转换(NAPT)的基本过程测试
图1-2中,4个带有内部地址的数据包到达HiPER,其中数据包1和2来自同一个内部地址但有不一样的源端口号,数据包3和4来自不一样的内部地址但具备相同的源端口号。经过NAPT,4个数据包都被转换到同一个外部地址,但每一个数据包都赋予了不一样的源端口号,所以区分了这4个数据包。当回复数据包到达时,NAPT就能根据回复数据包的目的地址和端口来区分该数据包应转发到的内部主机。spa
在Internet中使用NAPT时,全部不一样的TCP和UDP信息流看起来好像来源于同一个IP地址。这种方式经常使用于拨号上网,经过从ISP处申请的一个IP地址,将多个链接经过NAPT接入Internet。在实际使用中能够把NAPT和基本NAT结合起来,即将一组外部地址和端口转换结合起来。设计
NAPT为每个Session分配一个NAPT本身的端口号,依据此端口号来判断将收到的公网IP主机返回的TCP/IP数据包转发给那台内网IP地址的计算机。 在这里Session是虚拟的,UDP通信并不须要创建链接,可是对于NAPT而言,的确要有一个Session的概念存在。NAPT对于UDP协议包的 透明传输面临的一个重要的问题就是如何处理这个虚拟的Session。咱们都知道TCP链接的Session以SYN包开始,以FIN包结束,NAPT可 以很容易的获取到TCP Session的生命周期,并进行处理。可是对于UDP而言,就麻烦了,NAPT并不知道转发出去的UDP协议包是否到达了目的主机,也没有办法知道。而 且鉴于UDP协议的特色,可靠不好,所以NAPT必须强制维持Session的存在,以便等待将外部送回来的数据并转发给曾经发起请求的内网IP地址的计 算机。NAPT具体如何处理UDP Session的超时呢?不一样的厂商提供的设备对于NAPT的实现不近相同,也许几分钟,也许几个小时,些NAPT的实现还会根据设备的忙碌状态进行智能 计算超时时间的长短。blog
[192.168.0.6:1827]
| UDP Packet[src ip:192.168.0.6 src port:1827 dst ip:61.51.76.102 dst port 8098]
v
[pub ip: 61.51.99.86]NAT[priv ip: 192.168.0.1]
| UDP Packet[src ip:61.51.99.86 src port:9881 dst ip:61.51.76.102 dst port 8098]
v
[61.51.76.102:8098]
图四: NAPT 将内部发出的UDP协议包的源地址和源端口改变传输给公网IP主机。
[192.168.0.6:1827]
^
| UDP Packet[src ip:61.51.76.102 src port:8098 dst ip:192.168.0.6 dst port 1827]
[pub ip: 61.51.99.86]NAT[priv ip: 192.168.0.1]
^
| UDP Packet[src ip:61.51.76.102 src port:8098 dst ip:61.51.99.86 dst port 9881]
[61.51.76.102:8098]
图五: NAPT 将收到的公网IP主机返回的UDP协议包的目的地址和目的端口改变传输给内网IP计算机。
如今咱们大概明白了NAPT如何实现内网计算机和外网主机间的透明通信。如今来看一下咱们最关心的问题,就是NAPT是依据什么策略来判断是否要为一个请求发出的UDP数据包创建Session的呢?主要有一下几个策略:索引
A. 源地址(内网IP地址)不一样,忽略其它因素, 在NAPT上确定对应不一样的Session
B. 源地址(内网IP地址)相同,源端口不一样,忽略其它的因素,则在NAPT上也确定对应不一样的Session
C. 源地址(内网IP地址)相同,源端口相同,目的地址(公网IP地址)相同,目的端口不一样,则在NAPT上确定对应同一个Session
D. 源地址(内网IP地址)相同,源端口相同,目的地址(公网IP地址)不一样,忽略目的端口,则在NAPT上是如何处理Session的呢?生命周期
D的状况正式咱们关心和要讨论的问题。依据目的地址(公网IP地址)对于Session的创建的决定方式咱们将NAPT设备划分为两大类:
Symmetric NAPT:
对于到同一个IP地址,任意端口的链接分配使用同一个Session; 对于到不一样的IP地址, 任意端口的链接使用不一样的Session.
咱们称此种NAPT为 Symmetric NAPT. 也就是只要本地绑定的UDP端口相同, 发出的目的IP地址不一样,则会创建不一样的Session.
[202.223.98.78:9696] [202.223.98.78:9696] [202.223.98.78:9696]
^ ^ ^
| | |
v v v
9883 9882 9881
|
[NAT] /
^
|
v
[192.168.0.6:1827]
图六: Symmetric 的英文意思是对称。多个端口对应多个主机,平行的,对称的!
Cone NAPT:
对于到同一个IP地址,任意端口的链接分配使用同一个Session; 对于到不一样的IP地址,任意端口的链接也使用同一个Session.
咱们称此种NAPT为 Cone NAPT. 也就是只要本地绑定的UDP端口相同, 发出的目的地址不论是否相同, 都使用同一个Session.
[202.223.98.78:9696] [202.223.98.78:9696] [202.223.98.78:9696]
^ ^ ^
| /
v v v
9881
[NAT]
^
|
v
[192.168.0.6:1827]
图七: Cone 的英文意思是锥。一个端口对应多个主机,是否是像个锥子?
如今绝大多数的NAPT属于后者,即Cone NAT。本人在测试的过程当中,只好使用了一台日本的Symmetric NAT。还好不是本身的买的,我从不买日货, 但愿看这篇文章的朋友也自觉的不要购买日本的东西。Win9x/2K/XP/2003系统自带的NAPT也是属于 Cone NAT的。这是值的庆幸的,由于咱们要作的UDP穿透只能在Cone NAT间进行,只要有一台不是Cone NAT,对不起,UDP穿透没有但愿了,服务器转发吧。后面会作详细分析!
下面咱们再来分析一下NAPT 工做时的一些数据结构,在这里咱们将真正说明UDP能够穿透Cone NAT的依据。这里描述的数据结构只是为了说明原理,不具备实际参考价值,真正感兴趣能够阅读Linux的中关于NAT实现部分的源码。真正的NAT实现 也没有利用数据库的,呵呵,为了速度!
Symmetric NAPT 工做时的端口映射数据结构以下:
内网信息表:
[NAPT 分配端口] [ 内网IP地址 ] [ 内网端口 ] [ 外网IP地址 ] [ SessionTime 开始时间 ]
PRIMARY KEY( [NAPT 分配端口] ) -> 表示依据[NAPT 分配端口]创建主键,必须惟一且创建索引,加快查找.
UNIQUE( [ 内网IP地址 ], [ 内网端口 ] ) -> 表示这两个字段联合起来不能重复.
UNIQUE( [ 内网IP地址 ], [ 内网端口 ], [ 外网IP地址 ] ) -> 表示这三个字段联合起来不能重复.
映射表:
[NAPT 分配端口] [ 外网端口 ]
UNIQUE( [NAPT 分配端口], [ 外网端口 ] ) -> 表示这两个字段联合起来不能重复.
Cone NAPT 工做时的端口映射数据结构以下:
内网信息表:
[NAPT 分配端口] [ 内网IP地址 ] [ 内网端口 ] [ SessionTime 开始时间 ]
PRIMARY KEY( [NAPT 分配端口] ) -> 表示依据[NAPT 分配端口]创建主键,必须惟一且创建索引,加快查找.
UNIQUE( [ 内网IP地址 ], [ 内网端口 ] ) -> 表示这两个字段联合起来不能重复.
外网信息表:
[ wid 主键标识 ] [ 外网IP地址 ] [ 外网端口 ]
PRIMARY KEY( [ wid 主键标识 ] ) -> 表示依据[ wid 主键标识 ]创建主键,必须惟一且创建索引,加快查找.
UNIQUE( [ 外网IP地址 ], [ 外网端口 ] ) -> 表示这两个字段联合起来不能重复.
映射表: 实现一对多,的
[NAPT 分配端口] [ wid 主键标识 ]
UNIQUE( [NAPT 分配端口], [ wid 主键标识 ] ) -> 表示这两个字段联合起来不能重复.
UNIQUE( [ wid 主键标识 ] ) -> 标识此字段不能重复.
看完了上面的数据结构是更明白了仍是更晕了? 呵呵! 多想一下子就会明白了。经过NAT,内网计算机计算机向外连结是很容易的,NAPT会自动处理,咱们的应用程序根本没必要关心它是如何处理的。那么外部的计算机想访问内网中的计算机如何实现呢?咱们来看一下下面的流程:
c 是一台在NAPT后面的内网计算机,s是一台有外网IP地址的计算机。c 主动向 s 发起链接请求,NAPT依据上面描述的规则在本身的数据结构中记录下来,创建一个Session. 而后 c 和 s 之间就能够实现双向的透明的数据传输了。以下面所示:
c[192.168.0.6:1827] <-> [priv ip: 192.168.0.1]NAPT[pub ip: 61.51.99.86:9881] <-> s[61.51.76.102:8098]
因而可知,一台外网IP地址的计算机想和NAPT后面的内网计算机通信的条件就是要求NAPT后面的内网计算机主动向外网IP地址的计算机发起一个 UDP数据包。外网IP地址的计算机利用收到的UDP数据包获取到NAPT的外网IP地址和映射的端口,之后就能够和内网IP的计算机透明的进行通信了。
如今咱们再来分析一下咱们最关心的两个NAPT后面的内网计算机如何实现直接通信呢? 二者都没法主动发出链接请求,谁也不知道对方的NAPT的公网IP地址和NAPT上面映射的端口号。因此咱们要靠一个公网IP地址的服务器帮助二者来创建 链接。当两个NAPT后面的内网计算机分别链接了公网IP地址的服务器后,服务器能够从收到的UDP数据包中获取到这两个NAPT设备的公网IP地址和这 两个链接创建的Session的映射端口。两个内网计算机能够从服务器上获取到对方的NAPT设备公网IP地址和映射的端口了。
咱们假设两个内网计算机分别为A和B,对应的NAPT分别为AN和BN, 若是A在获取到B对应的BN的IP地址和映射的端口后,迫不急待的向这个IP
地址和映射的端口发送了个UDP数据包,会有什么状况发生呢?依据上面的原理和数据结构咱们会知道,AN会在本身的数据结构中生成一条记录,标识一个新 Session的存在。BN在收到数据包后,从本身的数据结构中查询,没有找到相关记录,所以将包丢弃。B是个慢性子,此时才慢吞吞的向着AN的IP地址 和映射的端口发送了一个UDP数据包,结果如何呢?固然是咱们指望的结构了,AN在收到数据包后,从本身的数据结构中查找到了记录,因此将数据包进行处理 发送给了A。A 再次向B发送数据包时,一切都时畅通无阻了。
PS:
端口映射的原理 内网的一台电脑要上因特网,就须要端口映射 端口映射分为动态与静态 动态端口映射: 内网中的一台电脑要访问新浪网,会向NAPT网关发送数据包,包头中包括对方 (新浪网)IP,端口和本机IP,端口,NAPT网关会把本机IP,端口替换成本身的公网一个 未使用的端口,而且会记下这个映射关系,为之后转发数据包使用。而后再把数据发判断 给新浪网,新浪网收到数据后作出反应,发送数据到NAPT网关的那个未使用的端口, 而后NAPT网关将数据转发给内网中的那台电脑,实现内网和公网的通信,当链接 关闭时,NAPT网关会释放分配给这条链接的端口,以便之后的链接能够继续使用。 NAPT网关的工做方式,由网关自动添加NAPT记录,一个映射关系 静态端口映射: 就是在NAPT网关上开放一个固定的端口,而后设定此端口收到的数据要转发给 内网的哪一个IP和端口,无论有没有链接,这个映射关系都会一直存在。就能够 让公网主动访问网的一个电脑。