当我从对称 nat 下的网络发送 tcp 或 udp 数据包时,我期望端口与我的计算机选择的端口不同,事实也是如此。但是,当我发送具有低 ttl 但仍设法离开 ISP 网络的 udp 数据包时,我收到一个错误 icmp 数据包,其中包含我最初作为有效负载发送的 udp 数据包,但端口由我的系统生成。
此时,我的疑问是 NAT 是否也无法控制 ICMP 数据包的内容。因为我知道有必要更改真正重要的层的标头,而不是有效负载。因此,对于 ICMP 数据包,只有源 IP 地址,而不是像我认为的那样,还有 echo“子数据包”的 IP 和端口。
答案1
当我从对称 nat 下的网络发送 tcp 或 udp 数据包时,我预计端口与我的计算机选择的端口不同,事实也如此。
那就是网络地址端口转换 (NAPT)NAT 版本。基本 NAT 不对传输协议执行任何操作。NAPT 必须为每种传输协议提供不同的表,这就是它仅支持 TCP、UDP 和 ICMP 的原因,因为 TCP 端口不是 UDP 端口,而 ICMP 不使用端口,它使用查询 ID。
我收到一个错误的 icmp 数据包,其中包含我最初作为有效负载发送的 udp 数据包,但带有我的系统生成的端口。
那是正确的。
此时我的疑问是 NAT 是否也无法获取 ICMP 数据包的内容。
对于必须返回发送应用程序的 ICMP 错误消息,NAPT 必须修复 ICMP 错误消息的内容,以便目标应用程序获取错误。ICMP 错误消息将原始数据包的第一部分作为其有效负载,以便将其返回到正确的应用程序。如果 NAPT 修改了传出数据包,它必须将返回的 ICMP 错误消息有效负载修改为原始地址,包括端口号。
因此,在 ICMP 数据包的情况下,只有源 IP 地址,而不是(我认为是这种情况)回显“子数据包”的 IP 和端口。
此行为的解释如下RFC 2663,IP 网络地址转换器 (NAT) 术语和注意事项:
3.3. ICMP 错误数据包转换
所有 ICMP 错误消息(重定向消息类型除外)在通过 NAT 时都需要修改。需要 NAT 修改的 ICMP 错误消息类型包括目标不可达、源抑制、超时和参数问题。NAT 不应尝试修改重定向消息类型。
对 ICMP 错误消息的更改将包括对嵌入在 ICMP 错误消息有效负载中的原始 IP 数据包(或其部分)的更改。为了使 NAT 对终端主机完全透明,必须修改嵌入在 ICMP 数据包有效负载中的 IP 报头的 IP 地址,必须相应地修改同一 IP 报头的校验和字段,以及随附的传输报头。还必须修改 ICMP 报头校验和,以反映对有效负载中的 IP 和传输报头所做的更改。此外,还必须修改正常的 IP 报头。
如您所见,NAT,尤其是 NAPT,非常耗费资源,这就是为什么一些供应商(例如思科)只允许在具有 NAT 硬件辅助的设备上使用 NAT。
答案2
NAT 是否会在 ICMP 有效负载中欺骗 TCP 端口?
由于您指的是 UDP 数据包,因此它不会在 ICMP 消息中欺骗 TCP 端口。但是,出于多种原因(围绕您的主机/应用程序需要知道如何在收到此类 ICMP 消息后进行处理并可能做出响应),它很可能会重写 ICMP 消息以反映原始 UDP 流量。
这可能因 NAT 实现而异,但让我们看一下您的示例(相信您在问题中陈述的所有内容都是准确的)。
- 您的系统发送一个 UDP 数据包。
- 网关对UDP数据包进行NAT。
- 在网络外部的某个地方,TTL 会减少并导致帧过期。执行此操作的路由器会发回 ICMP 超时消息。
停下来想一想。生成 ICMP 超时消息的路由器不会有“我最初发送的 udp 数据包”,因为它通过了您的 NAT 网关并进行了转换。换句话说,生成 ICMP 消息的路由器怎么会知道要放入 ICMP 消息的原始信息是什么?
原始 UDP 数据包能够出现在 ICMP 消息的有效负载中的唯一方式是您的 NAT 网关重写了它。