NAT的类型

根据NAT转换是对报文中的源地址进行转换还是对目的地址进行转换,NAT可以分为源NAT、目的NAT和双向NAT,下面我们分别介绍这三种NAT类型。

源NAT分类

源NAT在NAT转换时,仅对报文中的源地址进行转换,主要应用于私网用户访问公网的场景。当私网用户主机访问Internet时,私网用户主机发送的报文到达NAT设备后,设备通过源NAT技术将报文中的私网IPv4地址转换成公网IPv4地址,从而使私网用户可以正常访问Internet。

根据转换时是否同时转换源端口号,源NAT可以细分为如下几种类型,详见下图。

类别 描述 使用场景
NAT No-PAT 是一种只转换地址,不转换端口的NAT,可以实现私有地址到公网地址的一对一转换 适用于上网用户较少且公网地址数与同时上网的用户数量相同的场景
NAPT(PAT) NAT是一种同时转换地址和端口的 NAT。NAPT 使用一个地址池,地址池里有多个公网地址可供转换。NAPT 可以实现多个私网地址到一个或多个公网地址的转换 NAPT 适用于公网地址数量少,但需要上网的私有用户量大的场景
Easy IP 是一种特殊的 NAPT,Easy IP 使用出接口的公网 IP 地址作为 NAT 转换后的地址 适用于仅有一个公网 IPv4 地址的场景,或者需要使用出接口的公网 IPv4 地址上网的场景

目的NAT分类

目的NAT在NAT转换时,仅对报文中的目的地址和目的端口号进行转换,主要应用于公网用户访问私网服务的场景。当公网用户主机发送的报文到达NAT设备后,设备通过目的NAT技术将报文中的公网IPv4地址转换成私网IPv4地址,从而使公网用户可以使用公网地址访问私网服务。

根据转换前后的地址是否存在一种固定的映射关系,目的NAT可以细分为如下几种类型,详见下图。

类别 描述 使用场景
静态目的NAT 是一种转换报文目的IP地址的方式,转换前后的地址存在一种固定的映射关系 通常情况下,出于安全的考虑,不允许外部网络主动访问内部网络。但是某些情况下,还是希望能够为外部网络访问内部网络提供一种途径。例如公司要将内部网络中的资源提供给外部网络中的客户和出差员工访问,此时,可以使用静态目的 NAT
动态目的NAT 动态目的 NAT 是一种动态转换报文目的 IP 地址的方式,转换前后的地址不存在一种固定的映射关系 通常情况下,静态目的 NAT 可以满足大部分目的地址转换的场景。但是在某些情况下,希望转换后的地址不固定。例如,移动端通过转换目的地址访问无线网络,此时,可以使用动态目的 NAT
NAT Server 是一种特殊的静态目的 NAT,NAT Server 将发往私网服务器的报文中的公网地址转换为与之对应的私网地址 在一些特殊场景下,例如,学校或公司内部部署一些服务器对公网用户提供服务。由于这些服务器的地址一般都用于私网地址,公网用户无法直接访问,此时,可以使用 NAT Server技术,将服务器的私网地址映射成公网地址后供公网用户访问

双向NAT

双向NAT指的是在转换过程中同时转换报文的源信息和目的信息。双向NAT不是一个单独的功能,而是源NAT和目的NAT的组合。双向NAT是针对同一条流,在其经过设备时同时转换报文的源地址和目的地址。双向NAT主要应用在同时有外网用户访问内部服务器和私网用户访问内部服务器的场景。

STUN中定义的NAT类型

在STUN标准中,根据私网IP地址和端口到NAT出口的公网IP地址和端口的映射方式,把NAT分为如下四种类型,详见下图。

Full Cone NAT(完全锥型NAT)

所有从同一个私网IP地址和端口(IP1:Port1)发送过来的请求都会被映射成同一个公网IP地址和端口(IP:Port)。并且,任何外部主机通过向映射的公网IP地址和端口发送报文,都可以实现和内部主机进行通信。

这是一种比较宽松的策略,只要建立了私网IP地址和端口与公网IP地址和端口的映射关系,所有的Internet上的主机都可以访问该NAT之后的主机。

Restricted Cone NAT(限制锥型NAT)

所有从同一个私网IP地址和端口(IP1:Port1)发送过来的请求都会被映射成同一个公网IP和端口号(IP:Port)。与完全锥型NAT不同的是,当且仅当内部主机之前已经向公网主机发送过报文,此时公网主机才能向私网主机发送报文。

Port Restricted Cone NAT(端口限制锥型NAT)

与限制锥型NAT很相似,只不过它包括端口号。也就是说,一台公网主机(IP2:Port2)想给私网主机发送报文,必须是这台私网主机先前已经给这个IP地址和端口发送过报文。

Symmetric NAT(对称NAT)

所有从同一个私网IP地址和端口发送到一个特定的目的IP地址和端口的请求,都会被映射到同一个IP地址和端口。如果同一台主机使用相同的源地址和端口号发送报文,但是发往不同的目的地,NAT将会使用不同的映射。此外,只有收到数据的公网主机才可以反过来向私网主机发送报文。

这和端口限制锥型NAT不同,端口限制锥型NAT是所有请求映射到相同的公网IP地址和端口,而对称NAT是不同的请求有不同的映射。

STUN技术介绍

STUN产生背景

P2P(Point to Point,点到点)应用为互联网的主要应用之一。通常情况下,P2P应用服务器位于公网,P2P客户端位于私网。为了私网中的P2P客户端能够访问公网P2P应用服务器,需要部署NAT设备将私网IP地址转换为公网IP地址,并转换端口号。不同网络环境中部署的NAT设备,其地址映射行为和报文过滤行为不尽相同。因此部署NAT设备后可能会带来如下问题:

  • 不是所有的私网的P2P客户端之间均能直接建立P2P连接
  • 私网的P2P客户端间建立P2P连接的交互过程会有所不同。

STUN(Session Traversal Utilities for NAT,NAT环境下的会话传输) 是一种C/S架构的网络协议,用于帮助各类应用协议穿越NAT。STUN协议根据NAT设备的地址映射行为和报文过滤行为这两类特征,定义了不同的NAT类型。在P2P组网中,STUN协议使得P2P客户端具备了探测所在网络中的NAT设备和NAT类型,以及发现自己公网NAT地址的能力,继而P2P客户端可以根据对端NAT设备的NAT类型选择合适的交互过程建立穿越NAT设备的P2P连接。

四种NAT类型

STUN协议工作的核心是,根据NAT设备的映射和过滤行为判断出NAT类型。各种NAT类型的特征如下表所示。

image-1652073745425

NAT类型对P2P连接的影响

不同NAT类型的映射行为和过滤行为对建立P2P连接的影响如下:

  • 映射行为:P2P客户端经过NAT设备主动访问某个外部节点,NAT设备会建立地址映射表项,相当于为该外部节点访问P2P客户端创建了一个通道。不同的映射行为决定了P2P客户端访问不同的外部节点时,是否会创建不同的通道。
  • 过滤行为:NAT设备会对公网主动发往私网的报文进行过滤。对于不同的过滤行为,外部节点通过上述通道与私网中的P2P客户端建立连接时需要满足的条件不同。

由于上述影响,对于不同私网中的P2P客户端,只有各自所在网络中NAT设备的NAT类型为下表所示的组合时,P2P客户端之间才能通过一定的交互方式直接建立P2P连接。对于P2P客户端之间无法直接建立P2P连接的情况,需要网络管理员部署中转设备转发P2P客户端之间的数据报文。

image-1652073856701

STUN探测NAT类型

STUN的通信模式

私网P2P客户端判断自己所在网络中NAT设备的NAT类型时,需要在该客户端,以及客户端经过NAT设备后路由可达的某个公网节点上开启STUN功能。STUN功能采用客户端/服务器通信模式,STUN服务器(STUN Server)和STUN客户端(STUN Client)之间的基本工作流程如下:

  • STUN客户端主动向STUN服务器发送探测请求报文。
  • STUN服务器将STUN客户端地址转换后的公网IP和端口号填充到探测响应报文中。
  • STUN客户端从探测响应报文中获取并记录自己地址转换后的公网IP和端口号,并通过比较不同的探测响应报文中的公网IP和端口号来判断NAT类型。

STUN探测机制

STUN客户端通过STUN服务器探测本端NAT设备的NAT类型时,STUN服务器需要拥有两个公网IP地址,以及两个监听探测请求的端口号。具体的探测步骤如下。

image-1652073971351

image-1652073995532

image-1652074003968

image-1652074012160

典型应用

在SD-WAN网络中,CPE(Customer Provided Edge,用户提供的网络边缘)之间需要建立数据通道,以便进行用户数据报文转发。CPE之间建立的数据通道就属于P2P类型的连接。

如下图所示,不同分支站点的CPE穿越NAT设备建立P2P连接时,需要在CPE 1、CPE 2和RR(Route Reflector,路由反射器)上开启STUN功能。开启STUN功能后,CPE之间建立数据通道的步骤如下:

  1. CPE 1和CPE 2作为STUN客户端主动向作为STUN服务器的RR发送探测请求报文。
  2. CPE 1和CPE 2从RR回复的响应报文中获取到自己地址转换后的公网IP和端口号,并通过与STUN服务器多次交互协议报文确定NAT类型。
  3. CPE 1和CPE 2将自己地址转换后的公网IP和端口号、NAT类型发送给RR。
  4. RR将CPE 1和CPE 2的公网IP和端口号、NAT类型反射给对端CPE。
  5. CPE 1和CPE 2通过对端的公网IP和端口号、NAT类型确定是否可以直接建立数据通道,以及建立数据通道的交互过程。对于CPE之间无法直接建立数据通道的情况,需要网络管理员部署NAT transfer设备转发CPE之间的数据报文。

image-1652074282008

基本NAT和端口号转换

image-1652065224301

基本网络地址转换(Basic NAT)

这一种也可称作NAT或“静态NAT”,在RFC 2663中提供了信息。它在技术上比较简单,仅支持地址转换,不支持端口映射。Basic NAT要求对每一个当前连接都要对应一个公网IP地址,因此要维护一个公网的地址池。宽带(broadband)路由器通常使用这种方式来允许一台指定的设备去管理所有的外部链接,甚至当路由器本身只有一个可用外部IP时也如此,这台路由器有时也被标记为DMZ主机。由于改变了IP源地址,在重新封装数据包时候必须重新计算校验和,网络层以上的只要涉及到IP地址的头部校验和都要重新计算。

网络地址端口转换(NAPT)

这种方式支持端口的映射,并允许多台主机共享一个公网IP地址。
支持端口转换的NAT又可以分为两类:源地址转换和目的地址转换。前一种情形下发起连接的计算机的IP地址将会被重写,使得内网主机发出的数据包能够到达外网主机。后一种情况下被连接计算机的IP地址将被重写,使得外网主机发出的数据包能够到达内网主机。实际上,以上两种方式通常会一起被使用以支持双向通信。

利用端口号的唯一性实现了公网ip转换为私网ip的这一步。PAT(NAT重载)能够使用传输层端口号来标识主机,因此,从理论上说,最多可让大约65000台主机共用一个公有IP地址

NAPT维护一个带有IP以及端口号的NAT表,结构如下。
内网IP 外网IP
192.168.1.55:5566 219.152.168.222:9200
192.168.1.59:80 219.152.168.222:9201
192.168.1.59:4465 219.152.168.222:9202

NAPT

image-1652060526773

图示是一种常见的 NAPT 拓扑。当内网设备访问访问目标时,它发送包 [iAddr:iPort -> dAddr:dPort] 给路由器。路由器的 NAPT 程序转换内部地址,改写包为 [eAddr:ePort -> dAddr:dPort],之后转发到外部网络。反之,当访问目标答复内网设备时,它发送包 [dAddr:dPort -> eAddr:ePort] 给路由器,路由器接收后通过 NAPT 程序改写包为 [dAddr:dPort -> iAddr:iPort] 然后转发给内网设备。

可以看到,发送过程(内部到外部)中 NAPT 程序改写数据包的源地址,进行源 NAT(SNAT)。在接受过程(外部到内部)中改写数据包的目标地址,进行目标 NAT(DNAT)。这两个相对应的过程一并组成了 NAPT。

在改写包的过程中,最关键的过程就是确定 eAddr 与 ePort。这也是不同 NAPT 实现的主要区别。

锥形与对称

由于 NAPT 用到了传输层协议的标志,因此具体实现无法脱离具体的传输层协议,所以对 NAPT 的分类也是和传输层协议挂钩的。

首先介绍的就是最常见的一种对 UDP NAT 的分类:RFC3489 分类。RFC3489 把 UDP NAT 分成了:全锥体 NAT(Full Cone NAT)、地址限制锥体 NAT(Restricted Cone)、端口限制锥体 NAT(Port Restricted Cone)、对称 NAT(Symmetric NAT)。

理解这些不同 NAT 的关键是理解它们各自的实现原理,这就要介绍一个关键的数据结构 ——NAT 表。NAT 表记录了一次 NAT 需要的全部信息,比如内部地址、外部地址、过期时间等等。在发送、接收时,NAT 设备会根据数据包中地址查表或在不存在记录时填表,从而确定改写的 eAddr 与 ePort。

全锥体 NAT

Full cone NAT(全锥形NAT)

  • 全锥体 NAT 的 NAT 表存储:(iAddr, iPort[, eAddr], ePort)。由于一般情况下 NAT 设备都只有一个外部地址(除非是运营商 NAT 等等大型网络),所以之后我都会省略 eAddr。之后出现 ePort 的地方都可默认为 (eAddr, ePort)
  • 发送时,通过 (iAddr, iPort) 查出 (ePort)。如果查不到相关记录,则分配一个 ePort 并记录到 NAT 表。
  • 接收时,通过 (ePort) 查出 (iAddr, iPort)

可以发现,全锥体 NAT 下一个外部 IP 上的端口 ePort,会被唯一分给一个内网设备的端口 iAddr:iPort。所以同一时间内全锥体 NAT 最多只能分配 65535(实际还要少很多)个内网设备端口。而由于端口分配是一一对应的,所以其他外部地址也能通过 ePort 访问到iAddr:iPort。

image-1652060926358

地址限制锥体 NAT

Restricted Cone NAT(地址受限锥形NAT)

  • 地址限制锥体 NAT 的 NAT 表存储:(iAddr, iPort, ePort, dAddr)
  • 发送时,通过 (iAddr, iPort) 查出 (ePort)
  • 接收时,通过 (ePort, dAddr) 查出 (iAddr, iPort)

可以看到,比起全锥体 NAT,地址限制锥体 NAT 多存储了一个 dAddr。这让我们可以在一定程度上复用 NAT 设备的外部端口 ePort。比如对于这样的 NAT 表:

(192.168.10.2, 10086, 11451, 6.6.6.6)
(192.168.10.3, 10086, 11451, 8.8.8.8)

不难看出,11451 这个 ePort 得以被分给两个映射。不过坏处是,不同的外部服务器 dAddr 就没办法通过 ePort 访问之前的映射了,只有同一服务器的另一端口 dAddr:dPort 可以访问。

image-1652063540067

内部客户端必须首先发送数据包到对方(IP=X.X.X.X),然后才能接收来自X.X.X.X的数据包。在限制方面,唯一的要求是数据包是来自X.X.X.X。内部地址(iAddr:port1)映射到外部地址(eAddr:port2),所有发自iAddr:port1的包都经由eAddr:port2向外发送。外部主机(hostAddr:any)能通过给eAddr:port2发包到达iAddr:port1。(注:any指外部主机源端口不受限制,但是目的端口必须是port2。只有外部主机数据包的目的IP 为 内部客户端的ip,且目的端口为port2时数据包才被放行。)

端口限制锥体 NAT

  • 端口限制锥体 NAT 的 NAT 表存储:(iAddr, iPort, ePort, dAddr, dPort)
  • 发送时,通过 (iAddr, iPort) 查出 (ePort)
  • 接收时,通过 (ePort, dAddr, dPort) 查出 (iAddr, iPort)

可以发现,它比地址受限型 NAT 还要多查找了一个 dPort。因此如今同一个 dAddr:dPort 可以连接最多 65535 个内部端口 iAddr:iPort 了。比如对于 NAT 表:

(192.168.10.2, 10086, 11451, 6.6.6.6, 23333)
(192.168.10.3, 10086, 11451, 6.6.6.6, 10000)

可以看到它进一步提升了 ePort 的复用效果。当然代价是同一服务器的其他端口也不能通过 ePort 访问之前的映射了。

image-1652063553876

类似受限制锥形NAT(Restricted cone NAT),但是还有端口限制。
一旦一个内部地址(iAddr:port1)映射到外部地址(eAddr:port2),所有发自iAddr:port1的包都经由eAddr:port2向外发送。

在受限圆锥型NAT基础上增加了外部主机源端口必须是固定的。

对称 NAT

对称NAT(Symmetric NAT)

  • 对称 NAT 的 NAT 表存储:(iAddr, iPort, ePort, dAddr, dPort)
  • 发送时,通过 (iAddr, iPort, dAddr, dPort) 查出 (ePort)
  • 接收时,通过 (ePort, dAddr, dPort) 查出 (iAddr, iPort)

对称 NAT 与锥形 NAT 最大的不同就是对发送的限制。所有锥形 NAT 都有一个特点,就是一旦建立映射,iAddr:iPort 发送的包一定会被映射到 eAddr:ePort,而限制都只针对接收时的查表。也就是说,锥形 NAT 都是在分配外部端口给一个内部端口。而对称 NAT 就是把外部端口分配个一次 “连接” 了,在发送的时候也关注目标地址。比如 NAT 表:

(192.168.10.2, 10086, 11451, 6.6.6.6, 23333)
(192.168.10.2, 10086, 11452, 8.8.8.8, 10000)

可以看到,同一个内部端口可以映射到多个外部端口。因此端口分配不再是一对多而是多对多。所有从同一个内网(IP,端口)发送到同一个目的IP和端口的请求都会被映射到同一个IP和端口。换句话说(SIP,Sport, DIP, Dport)只要有一个发生变化都会使用不同的映射条目,即此NAT映射与报文四元组绑定。

image-1652063826564

每一个来自相同内部IP与端口,到一个特定目的地地址和端口的请求,都映射到一个独特的外部IP地址和端口。
同一内部IP与端口发到不同的目的地和端口的信息包,都使用不同的映射只有曾经收到过内部主机数据的外部主机,才能够把数据包发回

对称/非对称的区别主要在于:网关设备在实现NAT时,对于内网某主机的若干个UDP连接请求,网关设备对应地在外网上所建立的UDP端口数量。对称NAT是一个请求对应一个端口,非对称NAT是多个请求对应一个端口(象锥形,所以叫Cone NAT)。

行为描述

虽然 RFC3489 对 UDP NAT 给出了一个分类,但是这个分类显然不太能涵盖所有种类的 NAT。比如发送时,为什么不能通过 (iAddr, iPort, dAddr) 查表,而是分成了锥型和对称型呢?此外,这个分类还遗漏了其他的 NAT 实现细节,比如在 NAT 表中不存在相关记录时,要怎么生成新的 ePort?是优先复用还是随机分配?NAT 表项的过期时间到底是多久?基于种种问题,IETF 废弃了这种分类方式,并在 RFC4787 中重新制定了一套对 NAT 行为的描述,以针对各种不同的 NAT 实现。

RFC4787 中描述了多种 NAT 行为,这里选取其中相对重要的三个进行介绍:映射行为、过滤行为、端口分配行为。

映射行为

映射行为对应于我们之前介绍中的发送行为,也就是从内部网络发送至外部网络,主要可以分为三种:

  • 端点独立映射(Endpoint-Independent Mapping):发送时通过 (iAddr, iPort) 查表
  • 地址独立映射(Address-Dependent Mapping):发送时通过 (iAddr, iPort, dAddr) 查表
  • 地址与端口独立映射(Address and Port-Dependent Mapping):发送时通过 (iAddr, iPort, dAddr, dPort) 查表

所有锥型 NAT 都是端点独立映射,而对称 NAT 则是地址与端口独立映射。当查表使用的信息越多,唯一确定一个映射所需要的条件也就更多,对端点的复用效果就越好,但同时也降低了连通性(不同的连接中无法保持同一个端口映射)。

过滤行为

过滤行为对应于我们之前介绍中的接收行为,也就是从外部网络发送至内部网络,主要也是分为三种:

  • 端点独立过滤(Endpoint-Independent Filtering):接收时通过 (ePort) 查表
  • 地址独立过滤(Address-Dependent Filtering):接收时通过 (ePort, dAddr) 查表
  • 地址与端口独立过滤(Address and Port-Dependent Filtering):接收时通过 (ePort, dAddr, dPort) 查表

可以看到,1-3 分别对应了锥型 NAT 的三种类型,而对称 NAT 则是地址与端口独立过滤。当查表使用的信息越多,在接收外部网络数据包时的条件也就更加严苛,同样也是提高了端点的复用效果,但是降低了连通性。

通过行为分类,可以清楚的了解到 RFC3489 分类法的局限(遗漏了很多种行为组合),也能更好的理解四种 NAT—— 全锥体 NAT 最为宽松、对称 NAT 最为严格。

端口分配行为

端口分配行为是 RFC3489 分类法没有提到的,但是也是 NAT 的一个非常重要的行为。端口分配发生在第一次映射行为时,用来产生映射的目标端口 ePort。

  • 端口保留(port preservation):NAT 将尽可能保证 ePort == iPort。比如在映射时替换掉之前拿到 ePort 的内部端口,或者维护一个地址池,分配不同外部地址的 ePort 端口 eAddr:ePort。
  • 端口重载(port overloading):即使外部端口冲突也依旧进行端口保留。端口重载会影响相关程序的正确性,因此 RFC4787 要求 NAT 程序不可以具备端口重载行为。
  • 非端口保留(no port preservation):NAT 不刻意保证 ePort == iPort。