跳到主要内容

2.23. NAT Traversal (NAT 穿越)

2.23. NAT Traversal (NAT 穿越)

网络地址转换 (Network Address Translation, NAT) 网关是有争议的话题. 本节简要说明其含义以及对 IKE 流量的可能影响. 许多人认为 NAT 有害, 协议设计不应迁就其工作. IKEv2 确实规定了一些反直觉的处理规则, 以使 NAT 更可能正常工作.

NAT 主要因 IPv4 地址短缺而存在, 也有其他理由. 位于 NAT "后面" 的 IP 节点地址并非全球唯一, 而是来自在 NAT 后网络内唯一但很可能与其他 NAT 后节点重复的空间. 一般地, NAT 后节点可与同一 NAT 后其他节点及具有全球唯一地址的节点通信, 但不能与另一 NAT 后节点通信. 该规则有例外. 当这些节点与真实互联网上的节点建立连接时, NAT 网关将 IP 源地址 "翻译" 为可路由回网关的地址. 从互联网到网关的消息将目的地址 "翻译" 为可将分组路由到正确端节点的内部地址.

NAT 设计为对端节点 "透明". NAT 后节点与互联网上的节点通信时, 双方软件通常都无需修改. 对某些协议实现这种透明性比其他协议更难. 若协议在分组载荷中包含端点 IP 地址, 除非 NAT 网关理解该协议并同时修改首部与内部引用, 否则将失败. 此类知识本质上不可靠, 违反网络分层, 常导致微妙问题.

通过 NAT 建立 IPsec 连接会带来特殊问题. 若连接运行于传输模式, 更改分组上的 IP 地址会导致校验和失败, 且 NAT 无法修正校验和, 因其受密码保护. 即使在隧道模式, 也存在路由问题, 因为对 AH 与 ESP 分组地址做透明翻译需要 NAT 中的特殊逻辑, 而该逻辑具有启发式且不可靠. 因此 IKEv2 对 IKE 与 ESP 分组使用 UDP 封装. 该编码效率略低, 但更便于 NAT 处理. 此外, 防火墙可配置为允许经 UDP 封装的 IPsec 流量而不允许明文 ESP/AH, 或反之.

NAT 通常除地址外还翻译 TCP 与 UDP 端口号, 并利用入站分组的端口号决定将分组交给哪个内部节点. 因此, 尽管 IKE 分组必须发送到 UDP 端口 500 或 4500 且从该端口发出, 必须从任意端口接受 IKE 分组, 且响应必须发回分组来源端口. 这是因为分组经过 NAT 时端口可能被修改. 类似地, IKE 端点 IP 地址通常不包含在 IKE 载荷中, 因为载荷受密码保护, NAT 无法透明修改.

端口 4500 保留给经 UDP 封装的 ESP 与 IKE. 若 IPsec 端点发现其与通信方之间存在 NAT (见下文), 必须从端口 4500 发送所有后续流量, NAT 不应像对端口 500 那样特殊处理该端口.

发起方可以在开始时即对 IKE 与 ESP 使用端口 4500, 无论是否存在 NAT. 任一方使用端口 4500 时, 不要求发送经 UDP 封装的 ESP, 但必须能够处理收到的经 UDP 封装的 ESP 分组. 不得在端口 500 上进行 UDP 封装. 若支持网络地址转换穿越 (NAT-T, 即在 IKE_SA_INIT 期间交换了 NAT_DETECTION_*_IP 载荷), 所有设备必须随时能够接收并处理经 UDP 封装与未经 UDP 封装的 ESP 分组. 任一方可以独立于对方选择是否对 ESP 使用 UDP 封装. 但若检测到 NAT, 双方必须对 ESP 使用 UDP 封装.

支持 NAT 穿越 [NATREQ] 的具体要求列于下文. NAT 穿越支持为可选. 本节中, 标为 MUST 的要求仅适用于支持 NAT 穿越的实现.

  • IKE 发起方与响应方均必须在其 IKE_SA_INIT 分组中包含类型为 NAT_DETECTION_SOURCE_IP 与 NAT_DETECTION_DESTINATION_IP 的 Notify 载荷. 这些载荷可用于检测主机间是否存在 NAT 以及哪一端位于 NAT 后. 载荷在 IKE_SA_INIT 分组中的位置紧接 Ni 与 Nr 载荷之后 (在可选 CERTREQ 载荷之前).

  • NAT_DETECTION_SOURCE_IP 通知关联的数据为 SPI (按首部出现顺序), 发送该分组所用的 IP 地址与端口的 SHA-1 摘要.

    若发送方不知道将用哪个网络附件发送分组, 消息中可以存在多个 NAT_DETECTION_SOURCE_IP 载荷.

  • NAT_DETECTION_DESTINATION_IP 通知关联的数据为 SPI (按首部顺序), 该分组发送目的 IP 地址与端口的 SHA-1 摘要.

  • NAT_DETECTION_SOURCE_IP 或 NAT_DETECTION_DESTINATION_IP 通知的接收方可以将所供值与 SPI, 源或目的 IP 地址及端口 (分别对应) 的 SHA-1 散列比较, 若不匹配, 应启用 NAT 穿越. 若 NAT_DETECTION_SOURCE_IP 散列与收到的所有 NAT_DETECTION_SOURCE_IP 载荷均不匹配, 接收方若不支持 NAT 穿越, 可以拒绝连接尝试. 若 NAT_DETECTION_DESTINATION_IP 散列不匹配, 表示接收 NAT_DETECTION_DESTINATION_IP 载荷的系统位于 NAT 后, 该系统应按 [UDPENCAPS] 发送保活分组; 或者若不支持 NAT 穿越, 可以拒绝连接尝试.

  • 若收到的任一 NAT_DETECTION_SOURCE_IP 载荷与含该载荷的分组 IP 首部所得源 IP 与端口的期望值均不匹配, 表示发送这些载荷的系统位于 NAT 后 (即路径上某处将原分组源地址改为 NAT 设备地址). 此情况下, 接收载荷的系统应允许按后文所述动态更新对方系统 IP 地址.

  • IKE 发起方若存在 NAT_DETECTION_SOURCE_IP 或 NAT_DETECTION_DESTINATION_IP 载荷, 必须检查它们; 若与外层分组地址不匹配, 必须将与本 IKE SA 相关的后续全部 IKE 与 ESP 分组经 UDP 端口 4500 隧道传输.

  • 经 UDP 端口 4500 隧道传输 IKE 分组时, 在 IKE 首部前前置四个零八位组, 结果紧接 UDP 首部. 经 UDP 端口 4500 隧道传输 ESP 分组时, ESP 首部紧接 UDP 首部. 由于 ESP 首部前四八位组为 SPI, 而 SPI 不能合法为零, 总能区分 ESP 与 IKE 消息.

  • 实现必须处理收到的经 UDP 封装的 ESP 分组, 即使未检测到 NAT.

  • 传输模式 TCP 与 UDP 分组校验和修复所需的原始源与目的 IP 地址 (见 [UDPENCAPS]) 从交换关联的流量选择器获得. 传输模式 NAT 穿越时, 流量选择器必须恰好包含一个 IP 地址, 用作原始 IP 地址. 2.23.1 节有更详细说明.

  • 存在 NAT 设备仍删除仍活跃映射的情况 (例如保活间隔过长或 NAT 重启). 若主机收到完整性校验通过但端口或地址或两者与已验证分组关联 SA 所记录不一致的分组, 即可察觉. 发现此类已验证分组时, 不支持 IKEv2 移动与多宿主 (MOBIKE) [MOBIKE] 等其他恢复方法且不在 NAT 后的主机, 应将所有分组 (包括重传分组) 发到已验证分组中的 IP 地址与端口, 并应将该地址与端口组合存为 SA 的新地址 (即应动态更新地址). 位于 NAT 后的主机不应在已验证分组端口或地址不同时做此类动态地址更新, 否则会打开可能的 DoS 攻击面 (例如攻击者用单个分组即可中断连接). 此外, 动态地址更新只应响应新分组进行; 否则攻击者可用旧重放分组恢复地址. 因此, 仅在启用重放保护时才能安全地进行动态更新. IKEv2 与 MOBIKE 联用时, 上述动态地址更新会干扰 MOBIKE 从相同情况恢复的方式. 详见 [MOBIKE] 3.8 节.

2.23.1. Transport Mode NAT Traversal (传输模式 NAT 穿越)

与 NAT 穿越一起使用传输模式时, 需对 IKEv2 中使用的流量选择器做特殊处理. 完整场景如下:

+------+        +------+            +------+         +------+
|Client| IP1 | NAT | IPN1 IPN2 | NAT | IP2 |Server|
|node |<------>| A |<---------->| B |<------->| |
+------+ +------+ +------+ +------+

(其他场景均为该复杂情况的简化, 故讨论采用完整场景.)

本场景中有两个做地址翻译的 NAT: NAT A 与 NAT B. NAT A 为动态 NAT, 将客户端源地址 IP1 映射为 IPN1. NAT B 为静态 NAT, 配置为将到达 IPN2 的连接映射到网关地址 IP2, 即目的地址 IPN2 映射到 IP2. 客户端可通过连接 IPN2 连接到服务器. NAT B 不必是静态 NAT, 但客户端必须知道如何连接服务器, 这只有在其以某种方式知道 NAT B 外部地址即 IPN2 时才能做到. 若 NAT B 为静态 NAT, 可将其地址配置到客户端. 另一种选择是通过其他协议 (如 DNS) 发现, 但超出 IKEv2 范围.

本场景中, 客户端与服务器均配置为对源自客户端发往服务器的流量使用传输模式.

客户端开始为向服务器发送流量创建 IKEv2 SA 与 Child SA 时, 可能有一个触发分组, 源 IP 为 IP1, 目的 IP 为 IPN2. 其对等体授权数据库 (Peer Authorization Database, PAD) 与安全策略数据库 (Security Policy Database, SPD) 需有匹配这些地址的配置 (或通配项). 因是传输模式, 流量选择器与 IKE 分组外层 IP 地址使用完全相同地址. 传输模式下 TSi 与 TSr 载荷必须恰好各使用一个 IP 地址. 若有多个端口范围要协商, 可以有多个流量选择器, 但所有 TSi 项的 IP 地址必须为 IP1-IP1 范围, 所有 TSr 项必须为 IPN2-IPN2. TSi 与 TSr 的第一个流量选择器应尽可能具体, 含协议与端口号, 例如来自触发请求的分组.

NAT A 将 IKE 分组源地址从 IP1 换为 IPN1, NAT B 将目的地址从 IPN2 换为 IP2, 故分组到达服务器时流量选择器与客户端发送的完全相同, 但 IKE 分组 IP 地址已变为 IPN1 与 IP2.

服务器收到该分组时, 通常先按 ID 查 [IPSECARCH] RFC 4301 所述 PAD, 再按流量选择器查 SPD. 因 IP1 对服务器无实际意义 (客户端在 NAT 后的地址), 若使用传输模式, 据此查找无用. 另一方面, 服务器在找到匹配 SPD 项之前无法知道策略是否允许传输模式.

此情况下, 服务器应先确认发起方请求了传输模式, 再对流量选择器做地址替换. 需先将旧流量选择器 IP 地址存下供后续增量校验和修复使用 (TSi 中 IP 可作为原始源地址, TSr 中可作为原始目的地址). 之后, 若检测到对端在 NAT 后, 服务器将 TSi 载荷中的 IP 地址换为所收 IKE 分组的源地址 (即将 TSi 中 IP1 换为 IPN1). 若服务器端检测到自身在 NAT 后, 将 TSr 载荷中 IP 地址换为所收 IKE 分组的目的地址 (即将 TSr 中 IPN2 换为 IP2).

经此替换后, 流量选择器与 IKE UDP 源/目的地址一致, 服务器基于新流量选择器做 SPD 查找. 若找到项且允许传输模式, 则使用该项. 若找到项但不允许传输模式, 服务器可以撤销地址替换并用原始流量选择器重新做 SPD 查找. 若第二次查找成功, 服务器将使用对端发送的真实流量选择器建立隧道模式 SA.

传输模式下此地址替换是必要的, 因为 SPD 使用本地主机将看到的地址查找. 这还确保安全关联数据库 (Security Association Database, SAD) 中为隧道出口检查与回程分组添加的项使用本地操作系统栈所见的地址.

最常见情况是服务器 SPD 含匹配任意地址的通配项, 但本机制也允许为不同已知 NAT 外部地址等配置不同 SPD 项.

SPD 查找后, 服务器将基于所找到 SPD 项缩小流量选择器. 仍使用已替换的流量选择器, 因而回送的流量选择器 IP 地址为 IPN1 与 IP2; 仍可缩小协议号或端口范围. 为 Child SA 创建的 SAD 项使用服务器所见地址, 即 IPN1 与 IP2.

客户端收到服务器对 Child SA 的响应时做类似处理. 若建立了传输模式 SA, 客户端可将返回的原始流量选择器存为原始源与目的地址. 将流量选择器中的 IP 换为 IKE 分组 IP 首部中的地址: 将 IPN1 换为 IP1, IP2 换为 IPN2. 然后使用这些流量选择器验证 SA 与所发送流量选择器是否一致, 并安装 SAD 项.

传输模式 NAT 穿越规则摘要:

对提议传输模式的客户端:

  • TSi 项必须恰好一个 IP 地址, 且必须与 IKE SA 源地址一致.

  • TSr 项必须恰好一个 IP 地址, 且必须与 IKE SA 目的地址一致.

  • 第一个 TSi 与 TSr 流量选择器应尽可能具体, 含协议与端口, 例如来自触发分组.

  • 可以有多个 TSi 与 TSr 项.

  • 若选择了 SA 的传输模式 (即服务器响应中含 USE_TRANSPORT_MODE 通知):

    • 将原始流量选择器存为收到的源与目的地址.

    • 若服务器在 NAT 后, 将 TSr 项中的 IP 换为 IKE SA 远端地址.

    • 若客户端在 NAT 后, 将 TSi 项中的 IP 换为 IKE SA 本地地址.

    • 在除存储其原始内容外的任何用途之前完成地址替换, 包括验证对端是否正确缩小流量选择器, 创建 SAD 项等.

对客户端提议传输模式时的响应方:

  • 将收到的流量选择器 IP 存为原始源与目的地址, 以备撤销替换, 用作 [UDPENCAPS] 规定的 "真实源与目的地址", 以及 TCP/UDP 校验和修复.

  • 若客户端在 NAT 后, 将 TSi 项 IP 换为 IKE SA 远端地址.

  • 若服务器在 NAT 后, 将 TSr 项 IP 换为 IKE SA 本地地址.

  • 使用 ID 与替换后的流量选择器做 PAD 与 SPD 查找.

  • 若未找到 SPD 项, 或 (若找到) 该项不允许传输模式, 撤销流量选择器替换. 使用 ID 与原始流量选择器再次做 PAD 与 SPD 查找, 并同时查找隧道模式 SPD 项 (即回退到隧道模式).

  • 但若找到传输模式 SPD 项, 基于替换后的流量选择器与 SPD 项做正常流量选择缩小. 创建 SAD 项及向客户端回送流量选择器时使用所得流量选择器.