NAT(3)RFC3022 Traditional IP Network Address Translator (Traditional NAT)
Author:Once Day Date:2024年12月4日
本文翻译自RFC3022 - Traditional IP Network Address Translator (Traditional NAT)。
这篇文章总结了NAT转换的基本概念,属于传统NAT最新的描述文档。
下文中的[NAT-TERM]指的是RFC2663文档(IP Network Address Translator (NAT) Terminology and Considerations)。
文章目录
1. 概述
1.1 前言
本文档中描述的 NAT 操作扩展了 RFC 1631 中引入的地址转换,并包含一种新型网络地址和 TCP/UDP 端口转换。此外,本文档更正了 RFC 1631 中发布的校验和调整算法,并尝试详细讨论 NAT 操作和限制。
1.2 简介
基本网络地址转换或基本 NAT 是一种将 IP 地址从一个组映射到另一个组的方法,对最终用户透明。网络地址端口转换或 NAPT 是一种将许多网络地址及其 TCP/UDP(传输控制协议/用户数据报协议)端口转换为单个网络地址及其 TCP/UDP 端口的方法。这两个操作合称为传统 NAT,提供了一种将具有私有地址的领域连接到具有全局唯一注册地址的外部领域的机制。
1.3 介绍
当网络的内部 IP 地址由于隐私原因或因在网络外使用无效而无法在网络外使用时,就会需要进行 IP 地址转换。
本地域外的网络拓扑可以以多种方式发生变化。
客户可能会更换提供商,公司主干网可能会重组,
或者提供商可能会合并或拆分。每当外部拓扑随时间发生变化时,本地域内节点的地址分配也必须更改以反映外部变化。通过将更改集中到单个地址转换路由器,可以对域内的用户隐藏此类更改。
基本地址转换将(在许多情况下,除了[NAT-TERM]和本文档第 6 节中所述的情况外)允许私有网络中的主机透明地访问外部网络并允许从外部访问选择性本地主机。网络设置主要用于内部使用且偶尔需要外部访问的组织是此方案的良好候选者。
许多小型办公室、家庭办公室 (SOHO) 用户和远程办公员工的办公室中有多个网络节点,运行 TCP/UDP 应用程序,但服务提供商为其远程访问路由器分配了一个 IP 地址,用于访问远程网络。这个不断增长的远程访问用户群体将受益于 NAPT,它允许本地网络中的多个节点使用分配给其路由器的单个 IP 地址同时访问远程网络。
使用转换方法存在局限性。与会话有关的所有请求和响应都必须通过同一个 NAT 路由器进行路由。确定这一点的一种方法是让 NAT 基于存根域独有的边界路由器,其中所有 IP 数据包要么源自该域,要么发往该域。还有其他方法可以通过多个 NAT 设备来确保这一点。例如,私有域可以有两个不同的出口点到不同的提供商,来自私有网络中主机的会话流可以穿过具有最佳外部主机度量标准的 NAT 设备。当其中一个 NAT 路由器发生故障时,另一个可以为所有连接路由流量。但是,这种方法有一个警告,即在切换到新的 NAT 路由器时,重新路由的流量可能会失败。克服这个潜在问题的一种方法是路由器共享相同的 NAT 配置并交换状态信息以确保彼此的故障安全备份。地址转换与应用程序无关,通常伴随着特定于应用程序的网关 (ALG) 来执行有效载荷监控和更改。FTP 是 NAT 设备上最流行的 ALG。需要 ALG 干预的应用程序不得对其有效载荷进行编码,因为这样做会有效地禁用 ALG,除非 ALG 拥有解密有效载荷的密钥。
此解决方案的缺点是,它剥夺了 IP 地址的端到端意义,并通过增加网络状态来弥补这一点。因此,不能假设 IPSec 保证的端到端 IP 网络级安全性适用于使用 NAT 设备的终端主机。但是,这种方法的优点是,它可以在不更改主机或路由器的情况下安装。
文档中使用的术语(例如“地址域”、“透明路由”、“TU 端口”、“ALG”等)的定义可在 [NAT-TERM] 中找到。
2. 传统 NAT 概述
本文档中介绍的地址转换操作称为“传统 NAT”。本文档中不会探讨 NAT 的其他变体。在大多数情况下,传统 NAT 允许私有网络内的主机透明地访问外部网络中的主机。在传统 NAT 中,会话是单向的,从私有网络出站。可以使用预先选择的主机的静态地址映射,在例外情况下允许反向会话。基本 NAT 和 NAPT 是传统 NAT 的两种变体,其中基本 NAT 中的转换仅限于 IP 地址,而 NAPT 中的转换扩展到包括 IP 地址和传输标识符(例如 TCP/UDP 端口或 ICMP 查询 ID)。
除非另有说明,否则本文档中的地址转换或 NAT 将涉及传统 NAT,即基本 NAT 以及 NAPT。只有下图 1 中描述的存根边界路由器可以配置为执行地址转换。
\ | / . /
+---------------+ WAN . +-----------------+/
|Regional Router|----------------------|Stub Router w/NAT|---
+---------------+ . +-----------------+\
. | \
. | LAN
. ---------------
Stub border
Figure 1: Traditional NAT Configuration
2.1 基本 NAT 概述
基本 NAT 操作如下。通过将一组私有地址动态映射到一组全局有效网络地址,可以使具有一组私有网络地址的存根域能够与外部网络通信。如果本地节点的数量小于或等于全局集合中的地址,则每个本地地址都保证有一个全局地址可以映射到。否则,允许同时访问外部网络的节点受全局集合中地址数量的限制。可以将单个本地地址静态映射到特定的全局地址,以确保保证可以访问外部,或者允许外部主机通过固定的公共地址访问本地主机。可以使用相同的地址映射从本地节点发起多个同时会话。
存根域内的地址是该域的本地地址,在域外无效。因此,存根域内的地址可以被任何其他存根域重用。例如,单个 A 类地址可以被许多存根域使用。在存根域和主干之间的每个出口点都安装了 NAT。如果有多个出口点,那么每个 NAT 都具有相同的转换表就非常重要。
例如,在图 2 的示例中,存根 A 和 B 都在内部使用 A 类私有地址块 10.0.0.0/8 [RFC 1918]。
存根 A 的 NAT 被分配 C 类地址块 198.76.29.0/24。
存根 B 的 NAT 被分配 C 类地址块 198.76.28.0/24。C 类地址是全局唯一的,其他 NAT 盒不能使用它们。
\ | /
+---------------+
|Regional Router|
+---------------+
WAN | | WAN
| |
Stub A .............|.... ....|............ Stub B
| |
{s=198.76.29.7,^ | | v{s=198.76.29.7,
d=198.76.28.4}^ | | v d=198.76.28.4}
+-----------------+ +-----------------+
|Stub Router w/NAT| |Stub Router w/NAT|
+-----------------+ +-----------------+
| |
| LAN LAN |
------------- -------------
| |
{s=10.33.96.5, ^ | | v{s=198.76.29.7,
d=198.76.28.4}^ +--+ +--+ v d=10.81.13.22}
|--| |--|
/____\ /____\
10.33.96.5 10.81.13.22
Figure 2: Basic NAT Operation
当存根 A 主机 10.33.96.5 希望将数据包发送到存根 B 主机 10.81.13.22 时,它使用全局唯一地址 198.76.28.4 作为目的地,并将数据包发送到其主路由器。存根路由器具有网络 198.76.0.0 的静态路由,因此数据包被转发到 WAN 链路。但是,NAT 会在转发数据包之前将 IP 标头的源地址 10.33.96.5 转换为全局唯一地址 198.76.29.7。同样,返回路径上的 IP 数据包也会经历类似的地址转换。
请注意,这不需要对主机或路由器进行任何更改。例如,对于存根 A 主机而言,198.76.28.4 是存根 B 中主机使用的地址。在大多数情况下,地址转换对终端主机是透明的。当然,这只是一个简单的例子。还有许多问题需要探讨。
2.2 NAPT 概述
假设一个组织有一个私有 IP 网络和一个到服务提供商的 WAN 链接。私有网络的存根路由器在 WAN 链接上被分配一个全局有效地址,而组织中的其余节点的 IP 地址仅具有本地意义。在这种情况下,可以允许私有网络上的节点同时访问外部网络,使用单个注册的 IP 地址和 NAPT。NAPT 允许将类型(本地 IP 地址、本地 TU 端口号)的元组映射到类型(注册 IP 地址、分配的 TU 端口号)的元组。
此模型符合大多数小型办公室家庭办公室 (SOHO) 组使用单个服务提供商分配的 IP 地址访问外部网络的要求。可以通过静态映射注册 IP 地址的每个服务 TU 端口的本地节点来扩展此模型以允许入站访问。
在下面图 3 的示例中,存根 A 在内部使用 A 类地址块 10.0.0.0/8。末梢路由器的 WAN 接口由服务提供商分配了 IP 地址 138.76.28.4。
\ | /
+-----------------------+
|Service Provider Router|
+-----------------------+
WAN |
|
Stub A .............|....
|
^{s=138.76.28.4,sport=1024, | v{s=138.76.29.7, sport = 23,
^ d=138.76.29.7,dport=23} | v d=138.76.28.4, dport = 1024}
+------------------+
|Stub Router w/NAPT|
+------------------+
|
| LAN
--------------------------------------------
| ^{s=10.0.0.10,sport=3017, | v{s=138.76.29.7, sport=23,
| ^ d=138.76.29.7,dport=23} | v d=10.0.0.10, dport=3017}
| |
+--+ +--+ +--+
|--| |--| |--|
/____\ /____\ /____\
10.0.0.1 10.0.0.2 ..... 10.0.0.10
Figure 3: Network Address Port Translation (NAPT) Operation
当存根 A 主机 10.0.0.10 向主机 138.76.29.7 发送 telnet 数据包时,它使用全局唯一地址 138.76.29.7 作为目的地,并将数据包发送到其主路由器。存根路由器具有子网 138.76.0.0/16 的静态路由,因此数据包被转发到 WAN 链路。但是,NAPT 会将 IP 和 TCP 标头中的源地址 10.0.0.10 和源 TCP 端口 3017 的元组转换为全局唯一的 138.76.28.4 和唯一分配的 TCP 端口(例如 1024),然后再转发数据包。返回路径上的数据包会针对目标 IP 地址和目标 TCP 端口经历类似的地址和 TCP 端口转换。再次注意,这不需要对主机或路由器进行任何更改。转换是完全透明的。
在此设置中,仅允许 TCP/UDP 会话,并且必须源自本地网络。但是,有些服务(例如 DNS)需要入站访问。组织可能希望允许其他服务进行入站会话访问。可以在存根路由器上静态配置众所周知的 TU 端口服务 [RFC 1700],以将其定向到私有网络中的特定节点。
除了 TCP/UDP 会话之外,除 REDIRECT 消息类型外,ICMP 消息也可能由 NAPT 路由器监控。ICMP 查询类型数据包的转换方式与 TCP/UDP 数据包类似,因为 ICMP 消息头中的标识符字段将唯一地映射到已注册 IP 地址的查询标识符。ICMP 查询消息中的标识符字段由查询发送者设置,并在查询响应者的响应消息中不加改变地返回。因此,NAPT 路由器将 (本地 IP 地址、本地 ICMP 查询标识符) 的三元组映射到 (已注册 IP 地址、分配的 ICMP 查询标识符) 的三元组,以唯一地标识来自任何本地主机的所有类型的 ICMP 查询。后面的部分将讨论对 ICMP 错误消息的修改,因为这涉及对 ICMP 有效负载以及 IP 和 ICMP 报头的修改。在 NAPT 设置中,注册的 IP 地址与存根路由器 WAN 接口的 IP 地址相同,路由器必须确保区分源自自身的 TCP、UDP 或 ICMP 查询会话与源自本地网络节点的会话。所有入站会话(包括 TCP、UDP 和 ICMP 查询会话)都假定指向作为终端节点的 NAT 路由器,除非目标服务端口静态映射到本地网络中的其他节点。
由 NAPT 路由器提供服务的本地节点不允许进行除 TCP、UDP 和 ICMP 查询类型以外的会话。
3. 会话的翻译阶段
传统 NAT 的转换阶段与 [NAT-TERM] 中描述的相同。以下小节列出了特定于传统 NAT 的项目。
3.1 地址绑定
使用基本 NAT,当从私有主机发起第一个传出会话时,私有地址将绑定到外部地址。
此后,来自同一私有地址的所有其他传出会话将使用相同的地址绑定进行数据包转换。
在 NAPT 的情况下,许多私有地址被映射到单个全局唯一地址,绑定将从(私有地址,私有 TU 端口)的三元组到(分配的地址,分配的 TU 端口)的三元组。与基本 NAT 一样,当私有主机上的(私有地址,私有 TU 端口)的三元组发起第一个传出会话时,此绑定被确定。虽然这不是一种常见的做法,但可以让私有主机上的应用程序建立来自同一(私有地址,私有 TU 端口)三元组的多个同时会话。在这种情况下,(私有地址,私有 TU 端口)三元组的单一绑定可用于转换来自主机上同一三元组的所有会话的数据包。
3.2 地址查找和翻译
在建立地址绑定或(地址,TU 端口)三元组绑定(如果是 NAPT)后,可以为使用该绑定的每个连接维护一个软状态。属于同一会话的数据包将接受会话查找以进行转换。转换的确切性质将在后续部分中讨论。
3.3 地址解除绑定
当基于地址或(地址,TU 端口)三元组绑定的最后一个会话终止时,绑定本身也可能终止。
4. 数据包翻译
与 NAT 管理会话有关的数据包在任一方向都会进行转换。以下小节将详细介绍各个数据包转换问题。
4.1 IP、TCP、UDP 和 ICMP 报头操作
在基本 NAT 模型中,必须修改每个数据包的 IP 报头。此修改包括 IP 地址(出站数据包的源 IP 地址和入站数据包的目标 IP 地址)和 IP 校验和。
对于 TCP 和 UDP 会话,修改必须包括更新 TCP/UDP 报头中的校验和。这是因为 TCP/UDP 校验和还涵盖包含源和目标 IP 地址的伪报头。作为例外,不应修改校验和为 0 的 UDP 报头。对于 ICMP 查询数据包,不需要对 ICMP 报头进行进一步更改,因为 ICMP 报头中的校验和不涵盖 IP 地址。
在 NAPT 模型中,对 IP 报头的修改与基本 NAT 的修改类似。对于 TCP/UDP 会话,必须扩展修改以包括 TCP/UDP 报头中 TU 端口(出站数据包的源 TU 端口和入站数据包的目标 TU 端口)的转换。
ICMP 查询数据包中的 ICMP 报头也必须修改,以替换查询 ID 和 ICMP 报头校验和。在出站时,必须将私有主机查询 ID 转换为分配的 ID,在入站时则完全相反。必须更正 ICMP 报头校验和以考虑查询 ID 转换。
4.2 校验和调整
NAT 修改是基于每个数据包的,并且可能非常耗费计算资源,因为它们除了简单的字段转换之外还涉及一个或多个校验和修改。幸运的是,我们有以下算法,它使 IP、TCP、UDP 和 ICMP 报头的校验和调整变得非常简单和高效。由于所有这些报头都使用一补码和,因此只需计算转换前和转换后地址之间的算术差并将其添加到校验和即可。以下算法仅适用于偶数偏移(即,下面的 optr 必须位于距报头开头的偶数偏移处)和偶数长度(即,下面的 olen 和 nlen 必须是偶数)。示例代码(C 语言)如下。
void checksumadjust(unsigned char *chksum, unsigned char *optr,
int olen, unsigned char *nptr, int nlen)
/* assuming: unsigned char is 8 bits, long is 32 bits.
- chksum points to the chksum in the packet
- optr points to the old data in the packet
- nptr points to the new data in the packet
*/
{
long x, old, new;
x=chksum[0]*256+chksum[1];
x=~x & 0xFFFF;
while (olen)
{
old=optr[0]*256+optr[1]; optr+=2;
x-=old & 0xffff;
if (x<=0) { x--; x&=0xffff; }
olen-=2;
}
while (nlen)
{
new=nptr[0]*256+nptr[1]; nptr+=2;
x+=new & 0xffff;
if (x & 0x10000) { x++; x&=0xffff; }
nlen-=2;
}
x=~x & 0xFFFF;
chksum[0]=x/256; chksum[1]=x & 0xff;
}
4.3 ICMP错误数据包修改
ICMP 错误消息的更改将包括外层 IP 和 ICMP 报头的更改以及嵌入在 ICMP 错误消息有效负载中的数据包报头的更改。
为了使 NAT 对终端主机透明,必须修改嵌入在 ICMP 错误消息有效负载中的 IP 报头的 IP 地址,必须修改嵌入 IP 报头的校验和字段,最后,还必须修改 ICMP 报头校验和以反映有效负载的更改。
在 NAPT 设置中,如果嵌入在 ICMP 中的 IP 消息恰好是 TCP、UDP 或 ICMP 查询数据包,您还需要修改 TCP/UDP 报头中的相应 TU 端口号或 ICMP 查询报头中的查询标识符字段。
最后,还必须修改 ICMP 数据包的 IP 报头。
4.4 支持FTP
最流行的应用程序之一“FTP”([FTP]) 需要 ALG 来监控控制会话有效负载,以确定随后的数据会话参数。FTP ALG 是大多数 NAT 实现不可或缺的一部分。
FTP ALG 需要一个特殊的表来纠正 TCP 序列和确认号以及源端口 FTP 或目标端口 FTP。
表条目应具有源地址、目标地址、源端口、目标端口、序列号增量和时间戳。仅当看到 FTP PORT 命令或 PASV 响应时才会创建新条目。对于每个 FTP PORT 命令或 PASV 响应,序列号增量可能会增加或减少。序列号在出站时递增,确认号在入站时递减此增量。
对于基本 NAT,FTP 有效负载转换仅限于私有地址及其分配的外部地址(以 ASCII 编码为单独的八位字节)。然而,对于 NAPT 设置,必须扩展转换以包含地址八位字节后的 TCP 端口八位字节(以 ASCII 格式)。
4.5 支持DNS
考虑到传统 NAT 中的会话主要从私有域出站,DNS ALG 可以避免与传统 NAT 结合使用,如下所示。私有域内部的 DNS 服务器维护内部主机和可能的一些外部主机的名称到 IP 地址的映射。外部 DNS 服务器仅为外部主机维护名称映射,而不为任何内部主机维护名称映射。如果私有网络没有内部 DNS 服务器,则所有 DNS 请求都可能被定向到外部 DNS 服务器以查找外部主机的地址映射。
4.6 IP 选项处理
具有任何 IP 选项记录路由、严格源路由或松散源路由的 IP 数据报都将涉及记录或使用中间路由器的 IP 地址。NAT 中间路由器可以选择不支持这些选项,或者在处理选项时不转换地址。不转换地址的结果是源路由上的私有地址端到端暴露。这不应该危及数据包本身的遍历路径,因为每个路由器应该只查看下一跳路由器。
5. 其他问题
5.1 本地地址和全局地址的划分
为了使 NAT 按照本文档所述的方式运行,必须将 IP 地址空间划分为两部分 - 存根域内部使用的私有地址和全局唯一地址。任何给定的地址都必须是私有地址或全局地址。没有重叠。重叠的问题如下。假设存根 A 中的主机希望将数据包发送到存根 B 中的主机,但存根 B 的全局地址与存根 A 的私有地址重叠。在这种情况下,存根 A 中的路由器无法区分存根 B 的全局地址与其自己的私有地址。
5.2 私有地址空间推荐
[RFC 1918] 提出了有关私有网络地址空间分配的建议。互联网号码分配机构 (IANA) 为私有互联网提供了三个 IP 地址空间块,即 10.0.0.0/8、172.16.0.0/12 和 192.168.0.0/16。在 CIDR 之前的表示法中,第一个块只是一个 A 类网络号,而第二个块是一组 16 个连续的 B 类网络,第三个块是一组 256 个连续的 C 类网络。
决定使用上述地址空间中的 IP 地址的组织无需与 IANA 或互联网注册机构进行任何协调即可这样做。因此,许多独立组织可以同时私下使用该地址空间,并在其边界路由器上启用 NAT 操作。
5.3 跨 NAT 路由
运行 NAT 的路由器不应将私有网络通告给主干网。只有具有全局地址的网络才可能在存根之外为人所知。但是,NAT 从
存根边界路由器接收到的全局信息可以以通常的方式在存根中通告。
通常,NAT 存根路由器将配置静态路由,以通过 WAN链路将所有外部流量转发到服务提供商路由器,服务提供商路由器将配置静态路由,以通过 WAN链路将 NAT 数据包(即,目标 IP 地址在 NAT 管理的全局地址列表范围内的数据包)转发到NAT 路由器。
5.4 从基本 NAT 切换到 NAPT
在基本 NAT 设置中,当私有网络节点数量超过可映射的全局地址时(例如,将 B 类私有网络映射到 C 类全局地址块),在地址列表中的最后一个全局地址用完后,对某些本地节点的外部网络访问会突然切断。这非常不方便且有限制。可以通过可选地允许基本 NAT 路由器切换到地址列表中最后一个全局地址的 NAPT 设置来安全地避免此类事件。这样做将确保私有网络上的主机能够持续、不间断地访问大多数应用程序的外部节点和服务。但请注意,如果某些以前使用基本 NAT 的应用程序由于切换到 NAPT 而突然中断,可能会造成混乱。
6. NAT 限制
[NAT-TERM] 广义上涵盖了所有类型的 NAT 的限制。以下小节列出了传统 NAT 特有的限制。
6.1 隐私和安全
传统的 NAT 可以被视为提供隐私机制,因为会话是从私有主机单向的,并且私有主机的实际地址对外部主机不可见。
增强隐私的同一特性可能会使调试问题(包括安全违规)更加困难。 如果私有网络中的主机以某种方式滥用互联网(例如试图攻击另一台机器甚至发送大量垃圾邮件),则更难以追踪实际的麻烦来源,因为主机的 IP 地址隐藏在 NAT 路由器中。
6.2 LAN 接口上对 NAT 映射全局地址的 ARP 响应
NAT 必须仅在存根域的边界路由器上启用。文档中提供的示例用于说明基本 NAT 和 NAPT,它们维护了从 NAT 路由器到外部路由器(即服务提供商路由器)的 WAN 链接。
但是,如果 WAN 链接被 LAN 连接替换,并且用于 NAT 映射的全局地址空间的部分或全部属于与 LAN 段相同的 IP 子网,则 NAT 路由器将为属于同一子网的地址范围提供 ARP 支持。在这种情况下,使用基本 NAT 设置必须使用自己的 MAC 地址响应 NAT 映射全局地址的 ARP 请求。
如果 NAT 路由器没有响应这些请求,则网络中没有其他节点拥有这些地址的所有权,因此将得不到响应。这种情况不太可能发生在 NAPT 设置中,除非 NAPT 映射中使用的单个地址不是 NAT 路由器的接口地址(例如,从基本 NAT 切换到 NAPT 的情况,如上文 5.4 中所述)。
使用直接连接子网的地址范围进行 NAT 地址映射将避免服务提供商路由器上的静态路由配置。
作者认为,LAN 链接到服务提供商路由器并不常见。但是,供应商可能有兴趣选择支持代理 ARP,以防万一。
6.3 NAPT 设置中出站 TCP/UDP 碎片数据包的转换
在 NAPT 设置中,出站 TCP/UDP 片段(即来自私有主机的片段)的转换注定会失败。原因如下。只有第一个片段包含 TCP/UDP 标头,这对于将数据包与会话关联以进行转换是必需的。后续片段不包含 TCP/UDP 端口信息,而只是携带第一个片段中指定的相同片段标识符。假设两个私有主机向同一目标主机发送了分段 TCP/UDP 数据包。而且,它们恰好使用相同的片段标识符。当目标主机从相同的指定主机地址接收到两个不相关的数据报时,它们携带相同的片段 ID,无法确定数据报属于哪个会话。因此,两个会话都将损坏。
6.4 当前实施
业界有许多商业实现,它们遵循本文档中提供的 NAT 描述。Linux 公共域软件包含名为“IP 伪装”的 NAT。FreeBSD 公共域软件具有作为守护进程运行的 NAPT 实现。但请注意,Linux 源代码受 GNU 许可证保护,而 FreeBSD 软件受 UC Berkeley 许可证保护。Linux 和 FreeBSD 软件都是免费的,因此您可以购买这些软件的 CD-ROM,其费用仅比分发成本高一点。它们还可以从许多 FTP 站点在线获取,其中包含最新补丁。