NAT名字很准确,网络地址转换,就是替换IP报文头部的地址信息。NAT通常部署在一个组织的网络出口位置,通过将内部网络IP地址替换为出口的IP地址提供公网可达性和上层协议的连接能力。那么,什么是内部网络IP地址?
RFC1918规定了三个保留地址段落:10.0.0.0-10.255.255.255;172.16.0.0-172.31.255.255;192.168.0.0-192.168.255.255。这三个范围分别处于A,B,C类的地址段,不向特定的用户分配,被IANA作为私有地址保留。这些地址可以在任何组织或企业内部使用,和其他Internet地址的区别就是,仅能在内部使用,不能作为全球路由地址。这就是说,出了组织的管理范围这些地址就不再有意义,无论是作为源地址,还是目的地址。对于一个封闭的组织,如果其网络不连接到Internet,就可以使用这些地址而不用向IANA提出申请,而在内部的路由管理和报文传递方式与其他网络没有差异。
私有IP地址:
A类:10.0.0.0-10.255.255.255即10.0.0.0/8
B类:172.16.0.0-172.31.255.255
C类:192.168.0.0-192.168.255.255
对于有Internet访问需求而内部又使用私有地址的网络,就要在组织的出口位置部署NAT网关,在报文离开私网进入Internet时,将源IP替换为公网地址,通常是出口设备的接口地址。一个对外的访问请求在到达目标以后,表现为由本组织出口设备发起,因此被请求的服务端可将响应由Internet发回出口网关。出口网关再将目的地址替换为私网的源主机地址,发回内部。这样一次由私网主机向公网服务端的请求和响应就在通信两端均无感知的情况下完成了。依据这种模型,数量庞大的内网主机就不再需要公有IP地址了。
NAT作用:
数据包在内网与外网间互通时,对数据包的IP地址进行转换;由内部到外部时修改源IP地址,由外部到内部时修改目的IP地址。
上面的描述概括了NAT处理报文的几个关键特点:
1.网络被分为私网和公网两个部分,NAT网关设置在私网到公网的路由出口位置,双向流量必须都要经过NAT网关;
2. 网络访问只能先由私网侧发起,公网无法主动访问私网主机;
3. NAT网关在两个访问方向上完成两次地址的转换或翻译,出方向做源信息替换,入方向做目的信息替换;
4. NAT网关的存在对通信双方是保持透明的;
5. NAT网关为了实现双向翻译的功能,需要维护一张关联表,把会话的信息保存下来。
如果一个内部主机唯一占用一个公网IP,这种方式被称为一对一模型。此种方式下,转换上层协议就是不必要的,因为一个公网IP就能唯一对应一个内部主机。显然,这种方式对节约公网IP没有太大意义,主要是为了实现一些特殊的组网需求。比如用户希望隐藏内部主机的真实IP,或者实现两个IP地址重叠网络的通信。
NAT最典型的应用场景就如同图2描述的,一个组织网络,在出口位置部署NAT网关,所有对公网的访问表现为一台主机。这就是所谓的一对多模型。这种方式下,出口设备只占用一个由Internet服务提供商分配的公网IP地址。面对私网内部数量庞大的主机,如果NAT只进行IP地址的简单替换,就会产生一个问题:当有多个内部主机去访问同一个服务器时,从返回的信息不足以区分响应应该转发到哪个内部主机。此时,需要NAT设备根据传输层信息或其他上层协议去区分不同的会话,并且可能要对上层协议的标识进行转换,比如TCP或UDP端口号。这样NAT网关就可以将不同的内部连接访问映射到同一公网IP的不同传输层端口,通过这种方式实现公网IP的复用和解复用。这种方式也被称为端口转换PAT、NAPT或IP伪装,但更多时候直接被称为NAT,因为它是最典型的一种应用模式。
PAT:端口地址转换
NAPT:网络地址端口转换
在一对多模型中,按照端口转换的工作方式不同,又可以进行更进一步的划分。为描述方便,以下将IP和端口标记为(nAddr:nPort),其中n代表主机或NAT网关的不同角色。
全锥形NAT
其特点为:一旦内部主机端口对(iAddr:iPort)被NAT网关映射到(eAddr:ePort),所有后续的(iAddr:iPort)报文都会被转换为(eAddr:ePort);任何一个外部主机发送到(eAddr:ePort)的报文将会被转换后发到(iAddr:iPort)。
限制锥形NAT
其特点为:一旦内部主机端口对(iAddr:iPort)被映射到(eAddr:ePort),所有后续的(iAddr:iPort)报文都会被转换为(eAddr:ePort);只有 (iAddr:iPort)向特定的外部主机hAddr发送过数据,主机hAddr从任意端口发送到(eAddr:ePort)的报文将会被转发到(iAddr:iPort)。
端口限制锥形NAT
其特点为:一旦内部主机端口对(iAddr:iPort)被映射到(eAddr:ePort),所有后续的(iAddr:iPort)报文都会被转换为(eAddr:ePort);只有(iAddr:iPort)向特定的外部主机端口对(hAddr:hPort)发送过数据,由 (hAddr:hPort)发送到(eAddr:ePort)的报文将会被转发到(iAddr:iPort)。
对称型NAT
其特点为:NAT网关会把内部主机“地址端口对”和外部主机“地址端口对”完全相同的报文看作一个连接,在网关上创建一个公网“地址端口对”映射进行转换,只有收到报文的外部主机从对应的端口对发送回应的报文,才能被转换。即使内部主机使用之前用过的地址端口对去连接不同外部主机(或端口)时,NAT网关也会建立新的映射关系。
现实中的很多NAT设备是将这些转换方式混合在一起工作的,而不单单使用一种,所以这些术语只适合描述一种工作方式,而不是一个设备。比如,很多NAT设备对内部发出的连接使用对称型NAT方式,而同时支持静态的端口映射,后者可以被看作是全锥型NAT方式。而有些情况下,NAT设备的一个公网地址和端口可以同时映射到内部几个服务器上以实现负载分担,比如一个对外提供WEB服务器的站点可能是有成百上千个服务器在提供HTTP服务,但是对外却表现为一个或少数几个IP地址。
NAT在解决IPv4地址短缺问题上,并非没有副作用,其实存在很多问题。而NAT最大的弊端正在于破坏了IP端到端通信的能力。
首先,NAT使IP会话的保持时效变短。因为一个会话建立后会在NAT设备上建立一个关联表,在会话静默的这段时间,NAT网关会进行老化操作。这是任何一个NAT网关必须做的事情,因为IP和端口资源有限,通信的需求无限,所以必须在会话结束后回收资源。通常TCP会话通过协商的方式主动关闭连接,NAT网关可以跟踪这些报文,但总是存在例外的情况,要依赖自己的定时器去回收资源。而基于UDP的通信协议很难确定何时通信结束,所以NAT网关主要依赖超时机制回收外部端口。通过定时器老化回收会带来一个问题,如果应用需要维持连接的时间大于NAT网关的设置,通信就会意外中断。因为网关回收相关转换表资源以后,新的数据到达时就找不到相关的转换信息,必须建立新的连接。当这个新数据是由公网侧向私网侧发送时,就会发生无法触发新连接建立,也不能通知到私网侧的主机去重建连接的情况。这时候通信就会中断,不能自动恢复。即使新数据是从私网侧发向公网侧,因为重建的会话表往往使用不同于之前的公网IP和端口地址,公网侧主机也无法对应到之前的通信上,导致用户可感知的连接中断。NAT网关要把回收空闲连接的时间设置到不发生持续的资源流失,又维持大部分连接不被意外中断,是一件比较有难度的事情。在NAT已经普及化的时代,很多应用协议的设计者已经考虑到了这种情况,所以一般会设置一个连接保活的机制,即在一段时间没有数据需要发送时,主动发送一个NAT能感知到而又没有实际数据的保活消息,这么做的主要目的就是重置NAT的会话定时器。
其次,NAT在实现上将多个内部主机发出的连接复用到一个IP上,这就使依赖IP进行主机跟踪的机制都失效了。如网络管理中需要的基于网络流量分析的应用无法跟踪到终端用户与流量的具体行为的关系。基于用户行为的日志分析也变得困难,因为一个IP被很多用户共享,如果存在恶意的用户行为,很难定位到发起连接的那个主机。即便有一些机制提供了在NAT网关上进行连接跟踪的方法,但是把这种变换关系接续起来也困难重重。基于IP的用户授权不再可靠,因为拥有一个IP的不等于一个用户或主机。一个服务器也不能简单把同一IP的访问视作同一主机发起的,不能进行关联。有些服务器设置有连接限制,同一时刻只接纳来自一个IP的有限访问(有时是仅一个访问),这会造成不同用户之间的服务抢占和排队。有时服务器端这样做是出于DOS攻击防护的考虑,因为一个用户正常情况下不应该建立大量的连接请求,过度使用服务资源被理解为攻击行为。但是这在NAT存在时不能简单按照连接数判断。总之,因为NAT隐蔽了通信的一端,把简单的事情复杂化了。
我们来深入理解NAT一下对IP端到端模型的破坏力。NAT通过修改IP首部的信息变换通信的地址。但是在这个转换过程中只能基于一个会话单位。当一个应用需要保持多个双向连接时,麻烦就很大。NAT不能理解多个会话之间的关联性,无法保证转换符合应用需要的规则。当NAT网关拥有多个公有IP地址时,一组关联会话可能被分配到不同的公网地址,这通常是服务器端无法接受的。更为严重的是,当公网侧的主机要主动向私网侧发送数据时,NAT网关没有转换这个连接需要的关联表,这个数据包无法到达私网侧的主机。这些反方向发送数据的连接总有应用协议的约定或在初始建立的会话中进行过协商。但是因为NAT工作在网络层和传输层,无法理解应用层协议的行为,对这些信息是无知的。NAT希望自己对通信双方是透明的,但是在这些情况下这是一种奢望。
此外,NAT工作机制依赖于修改IP包头的信息,这会妨碍一些安全协议的工作。因为NAT篡改了IP地址、传输层端口号和校验和,这会导致认证协议彻底不能工作,因为认证目的就是要保证这些信息在传输过程中没有变化。对于一些隧道协议,NAT的存在也导致了额外的问题,因为隧道协议通常用外层地址标识隧道实体,穿过NAT的隧道会有IP复用关系,在另一端需要小心处理。ICMP是一种网络控制协议,它的工作原理也是在两个主机之间传递差错和控制消息,因为IP的对应关系被重新映射,ICMP也要进行复用和解复用处理,很多情况下因为ICMP报文载荷无法提供足够的信息,解复用会失败。IP分片机制是在信息源端或网络路径上,需要发送的IP报文尺寸大于路径实际能承载最大尺寸时,IP协议层会将一个报文分成多个片断发送,然后在接收端重组这些片断恢复原始报文。IP这样的分片机制会导致传输层的信息只包括在第一个分片中,NAT难以识别后续分片与关联表的对应关系,因此需要特殊处理。
静态一对一地址映射:
这种工作方式下,NAT把一个私网地址和一个公网地址做静态关联,在从内而外的方向,将源IP匹配的私网IP替换为公网IP,反方向则将目的IP匹配公网IP的报文替换为私网IP。网络层以上的部分不进行替换处理,只修正校验和。
静态多对多地址映射:
这种方式与上一种类似,只是把一段私网地址映射到一段公网地址。工作机制与前述的方式没有差别,只是简化配置工作量。
动态端口映射:
这是最基本的工作方式,即前面多次介绍的将一段内网地址动态翻译为一个或多个公网IP,同时对传输层端口或其他上层协议信息进行转换,以实现IP复用。对由内而外的报文,替换源地址和端口,反向报文替换目的地址和端口。仅以连接公网的接口IP作为NAT转换的公网地址时,这种配置最简化,又被称为EasyIP。当以一段公网IP地址作为NAT转换地址时,需要配置一个地址池,NAT会自动在地址池中选择使用公网IP。
动态地址映射(no-pat):
这是介于静态多对多地址映射和动态端口映射方式之间的一种工作机制。当有一个私网向公网侧访问到达NAT网关时,NAT网关会检查这个私网IP是否已经有关联的公网IP映射。如果已经存在,则按照转换表直接替换IP,不修改上层协议。如果不存在关联表项,则在空闲的公网IP池中占用一个IP,并写入关联表中,以后按照这个关联关系进行地址转换。当这个私网主机发起的所有对外访问均关闭或超时后,回收公网IP。这种方式可以理解为一组内网主机抢占式地共享一个公网IP地址池。当公网IP地址池用完以后,新连接将无法建立。
静态端口映射:
通过静态配置,把一个固定的私网IP地址和端口关联到一个公网地址和端口上。这种方式等同于前面介绍过的全锥模式,但是不需要内网主机首先发出报文。这种方式适用于在NAT网关上把一个知名服务(如HTTP)映射到一个内部主机上,也称为port forwarding。
应用层网关(ALG):
在所有NAT产品实现中,ALG是一个必需的功能组件。但在不同实现中,有些产品可以动态加载不同的ALG模块,有些产品可以提供ALG开关控制,有些则不提供任何用户接口。ALG解析上层应用协议的内容,并且根据需要修改IP和端口相关信息,创建和维护附加的关联表项。
NAT转换关联表:
无论哪一种NAT工作方式,都要用到地址转换关联表,在不同产品的实现中,这个关联表的存储结构和在IP转发中调用的方式有很大不同。关联表中会记录源IP、目的IP、连接协议类型、传输层源端口、目的端口,以及转换后的源IP、源端口,目的IP、目的端口信息,这里的源和目的都是对应于从内网到外网的访问方向。依据NAT具体工作方式,这些信息可能全部填充,也可能部分填充。例如只按照IP做静态映射的方式,就不需要填入任何端口相关信息;对于静态端口映射,则只填入源相关的内容,而目的端的信息为空。