NAT穿透工作原理 转载
前言 我们在 Tailscale 工作原理 中涵盖了很多内容。但是,我们只是略微提及了如何绕过 NAT(网络地址转换器),而且无论设备之间有什么障碍,我们都假设他们能直连。下面我们就来详细讨论下。 我们先从一个简单的问题入手:在两台机器之间建立点对点连接。在 Tailscale 的案例中,我们希望建立一个 WireGuard® 隧道,但这其实并不重要。我们使用的技术应用广泛,是许多人几十年来研究的成果。例如, WebRTC 就利用这套技术在 Web 浏览器之间传输点对点音频、视频和数据。VoIP 电话和一些视频游戏也使用了类似的技术,尽管并非总是成功。 我们将对这些技术进行一般性讨论,并在适当情况下以 Tailscale 等为例进行说明。假设您正在创建自己的协议,并且需要实现 NAT 穿透。您需要两样东西: 首先,协议应该基于 UDP。虽然也可以使用 TCP 进行 NAT 穿透,但这会使原本就相当复杂的问题更加复杂,甚至可能需要对内核进行定制,具体取决于你想要实现的深度。所以下面我们重点讨论下 UDP。如果你因为希望在 NAT 穿透完成后建立面向流的连接而选择 TCP,不妨考虑改用 QUIC。QUIC 基于 UDP 构建,因此我们可以专注于使用 UDP 进行 NAT 穿透,最终仍然能够获得良好的流传输协议。 其次,你需要直接控制发送和接收网络数据包的网络套接字。通常情况下,你不能直接使用现有的网络库来穿透 NAT,因为你需要发送和接收一些额外的、不属于你正在使用的“主”协议的数据包。有些协议将 NAT 穿透与其他功能紧密集成在一起(例如 WebRTC)。但如果你要自己构建 NAT 穿透机制,最好将 NAT 穿透视为一个独立的实体,它与你的主协议共享一个套接字。两者并行运行,互相支持。 简单来说,标准的网络库只负责传输协议数据(如 TLS 握手、HTTP 请求)。但基于 NAT 穿透的连接需要你在同一个端口上,既发送业务数据,又发送用于维持连接、探测路径的“额外数据包”。如果你无法直接控制 socket,你就没法塞进这些“私货” ...