ICMP 打洞中的缺陷?

Flaw in ICMP holepunching?

如果有问题的 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

力学

pwnat:

中描述的 ICMP 打洞的快速概述

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

问题

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

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

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

提前致谢:)

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

pwnat 现在很少用了。几年前我碰巧知道这个 icmp punching 的东西,并对这个想法很感兴趣。看了pwnat的源码,自己用Go重新实现了一遍。只有进行简单地址转换的基本 NAT 设备(rfc 1631 描述)才可以使用它,任何具有强大 NAPT 实现的 NAPT 设备都不能使用。

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

when the NAT device receives the ICMP Error packet from the Private Realm, the NAT device uses the packet embedded within the ICMP Error message (i.e., the IP packet from the client to the server) to look up the NAT Session to which the embedded packet belongs. If the NAT device does not have an active mapping for the embedded packet, the NAT SHOULD silently drop the ICMP Error packet.

表示客户端的ICMP Time Exceeded 报文无法通过NAT-C。 This paper确实提到了这种情况并推荐了其他解决方案。