ICMP 打洞有缺陷吗?

mxx*_*xxk 4 nat icmp hole-punching pwnat

如果相关 NAT 设备重写出站 ICMP 数据包,ICMP NAT 穿越应该如何工作?

图表

=========================================================================================
| CLIENT  | <---> |  NAT-C  | <---> { internet } <---> |  NAT-S  | <---> | SERVER |
=========================================================================================
                  19.19.19.19   (external addresses)   72.72.72.72
192.168.0.2       192.168.0.1   (internal addresses)   172.16.0.1       172.16.0.2
Run Code Online (Sandbox Code Playgroud)

力学

ICMP 打洞的快速概述,如下所述pwnat

SERVER向其他主机(例如3.3.3.3)发送 ICMP 回显请求数据包 (ping) 以打开 中的漏洞NAT-S。当CLIENT想要连接时,它会向 发送一个 ICMP 超时数据包NAT-S,该数据包应该路由到SERVER。为了使所述路由正常工作,CLIENT通过在 ICMP 超时数据包中嵌入3.3.3.3它期望SERVER首先发送的相同数据包 (ICMP Echo to ) 来构造 ICMP 超时数据包。

问题

如果需要嵌入与其在 ICMP 超时回复中CLIENT留下的相同(ICMP 回显请求)数据包,则它必须知道数据包的查询 ID。但它怎么知道这个查询ID呢?NAT-S

根据RFC 3022 第 2.2 节,当NAT-S遇到出站 ICMP Echo 请求时,它将数据包的查询 ID 字段重写为唯一的外部查询 ID,以便它可以将具有相同查询 ID 的未来 ICMP Echo 回复路由到SERVER

鉴于上述问题,ICMP 打洞背后的前提似乎pwnat是无效的,并且它永远不会起作用。我在这里错过了什么吗?

提前致谢 :)

jfl*_*fly 5

您对查询 ID 的看法是正确的。

pwnat现在很少工作了。我几年前碰巧知道了 icmp 打孔的事情,并对这个想法感兴趣。我阅读了pwnat的源代码并自己用Go重新实现了它。只有执行简单地址转换的基本 NAT 设备(rfc 1631描述)可以与其一起工作,任何具有强大 NAPT 实现的 NAPT 设备都无法使用。

除了标识符问题之外,(顺便说一句, pwnat的源代码使用0作为原始请求的标识符)pwnat没有给出原始ip标头的正确校验和,这可能导致NAT-S丢弃TTL超出的消息(如果数据包可以到达那里)。
更严重的是,根据rfc 5508

当 NAT 设备从私有领域接收到 ICMP 错误数据包时,NAT 设备使用嵌入在 ICMP 错误消息中的数据包(即从客户端到服务器的 IP 数据包)来查找嵌入数据包到的 NAT 会话属于. 如果 NAT 设备没有嵌入数据包的活动映射,则 NAT 应静默丢弃 ICMP 错误数据包。

这意味着来自客户端的 ICMP 超时数据包不会通过 NAT-C。本文确实提到了这种场景并推荐了其他解决方案。