我正在构建一个点对点协议,其中节点通过共享它们所连接的 IP 地址来通告其他节点的存在。此功能称为“对等发现”。我正在运行的节点之一具有静态 IPv4,因此所有其他节点都可以连接到该节点。我们称这台机器为“A”。
当我通过 IPv4 从办公室中连接 wifi 的计算机连接到 A 时,这些计算机连接不良,对等发现不起作用。但当我通过 IPv6 连接时,对等发现效果非常好。办公机器和 A 在不同的网络上。
使用 IPv6,办公室计算机上自我报告的 IP ( ip -6 addr
) 与 A 看到的相匹配。当我通过 IPv4 连接时,两个报告的地址之间不匹配
这是因为办公室机器从办公室 WiFi 路由器获取经过 NAT 处理的 IPv4 地址和全球唯一的 IPv6 地址吗?
其他 p2p 协议上也会发生这种情况吗?
所有机器都通过 TCP 协议连接。我构建的对等发现功能只需共享已连接节点的 IP 地址及其宣布的用于传入连接的端口即可工作。
我并不是要求修复 IPv4。我只是询问 IPv4 与 IPv6 的典型 NAT 行为,以及其他 p2p 应用协议(例如 BitTorrent 或比特币)是否也会遇到这种行为。
这有一些问题。假设服务器在 NAT 外部,而所有客户端都在内部,这意味着服务器只会学习 NAT 网关的地址,这对服务器甚至任何其他客户端都不起作用,即使其他客户端在内部。(也就是说,客户端 B 必须连接到客户端 A 的内部地址,而不是其公共 NAT 网关地址。)
据我所知,至少有一些现代的对等发现协议(例如 WebRTC)让客户端与发现服务器显式共享其所有IP 地址 - 例如,即使您通过 IPv4 连接,服务器(和其他对等点)也会了解您的 IPv6 地址、其他IPv4 地址(内部、外部,也许是内部 #2)等。
IPv6 基本上避免了这个问题,因为(通常!)没有地址转换;然而,IPv6 主机拥有两组地址(全局地址和本地地址)的情况相当常见,因此报告这两个地址仍然很有用。
更一般地,假设两个对等点位于 NAT 的不同端(或者更糟糕的是,都位于单独的 NAT 后面),“用于传入连接的已公布端口”通常不会通过典型的 NAT 工作,除非客户端专门使用 NAT- PMP 或 UPnP IGD 从其本地 NAT 网关请求入站端口映射(并且仅当只有一层 NAT、没有惰性“堆叠路由器”设置且没有 ISP 级 CGNAT 时才有效)。如果端口映射不可用,您将需要“NAT 穿越”机制。
是的,这意味着 NAT(至少其中一层)。实际上,NAT 始终是“1:多”NAT,其中多个主机共享相同的外部 IP 地址,在这种情况下,如果没有某个 TCP 端口到某个 TCP 端口的显式映射,从“外部”到该地址的新入站连接将无处可去。内部地址(从技术上讲,它们会到达 NAT 网关本身,而 NAT 网关只会拒绝它们),而来自“内部”的新入站连接即使使用显式映射也将无处可去(NAT-hairpin 本身就是一个令人头痛的问题)。
因此,如果您希望从“内部”进行连接(例如同一办公室中的两台相邻 PC),那么客户端必须自行报告其地址,而不是依赖“服务器所看到的内容”。我远不是这个领域的专家,但
webrtc ice candidates
可能是一个开始研究的地方。同时,对于来自“外部”的连接,您的选择是 a) 让客户端尝试使用 NAT-PMP 和/或 UPnP IGD 保留端口映射 – 并且,再次自我报告,而不仅仅是他们从网关收到的保留端口(这很可能与客户端正在侦听的端口不同),而且还有“外部”地址;b) 使用 NAT 穿越机制,例如 STUN,该机制通常不适用于 TCP。