✦工程

NAT 穿透详解:点对点远程桌面如何穿过你的路由器。

你只有一个公网 IP,路由器后面却挂着十几台设备。你的 iPad 用着蜂窝网络,和家隔着三层网络。不知怎么的,远程桌面应用在一秒之内,就在它们之间打开了一条直接连接,而且通常中间没有任何中继。这背后的魔法究竟是怎么回事:ICE、STUN、TURN、打洞,以及关于对称型 NAT 那个尴尬的真相。

为什么这很重要

设想一个周二的早晨。你的 Mac mini 在家里,位于只有一个公网 IPv4 地址的路由器后面。你的 iPad 在火车上,使用运营商的移动网络,那里有自己好几层的地址转换。这两台设备之间至少隔着两层 NAT,很可能是三层。默认情况下,两台机器都无法从外部互联网访问。

然而你在 iPad 上打开 Remio,点一下那台 Mac,一秒钟后你就看到了自己的桌面。视频和输入直接在两台设备之间流动:没有云端中继,中间也没有任何代理对你的屏幕重新编码。

让这一切成为可能的技术有个名字,叫 NAT 穿透,背后是一整套定义明确的协议:STUN、TURN 和 ICE。它们正是 WebRTC 用于浏览器视频通话的那些协议,也是任何现代点对点远程桌面能够避免把你的屏幕画面经由第三方数据中心的原因。本文会逐一介绍每个协议做什么、为什么存在,以及它们如何配合,在躲在路由器后面的两台设备之间找到延迟最低的路径。

60 秒讲清 NAT 问题

互联网最初的设计,是让每台设备都有自己的公网可路由地址。整个 IPv4 地址空间只有大约 43 亿个地址,在 1981 年绰绰有余,到 1990 年代末就显然不够了。

变通的办法是网络地址转换(NAT)。你的路由器从运营商那里得到一个公网 IPv4 地址。在你家里,每台设备都从一段保留地址范围中获得一个私有地址(通常是 192.168.x.x 或 10.x.x.x)。当你的笔记本发出一个数据包时,路由器会把源地址改写成它自己的公网 IP,记住这条映射,然后转发出去。回复到达时,路由器查找映射,把目标地址再改写回你的笔记本。

这正是传入连接默认无法工作的原因。从外面看,你的笔记本没有地址,只有路由器有。陌生人发往 your-router-public-ip:5060 的数据包,会撞上一台没有对应映射的路由器,被直接丢弃。

对于点对点应用来说,这就是全部的游戏规则。双方都位于路由器后面,而路由器只有在记得自己先发出过东西时,才会转发数据包。任何一方都不能简单地“呼叫”对方,而必须配合各自的路由器,打开一条临时通路。

打洞:让防火墙放你回来

诀窍在这里。路由器的 NAT 表以一个五元组为键:源 IP、源端口、目标 IP、目标端口和协议。当你的设备向 1.2.3.4:5678 发出一个出站 UDP 数据包时,路由器会创建一条临时条目,意思是“如果有任何 UDP 数据包从 1.2.3.4:5678 回到我的公网 IP 的端口 X,就把它转发给这台设备的端口 Y。”

这条条目会在一段时间内存在,通常是 30 到 60 秒,之后如果没有东西刷新它,就会过期。在这段时间内,来自该目标地址的任何数据包都会被接受。

这就是点对点应用利用的钥匙孔。如果双方都知道对方的公网地址,就可以同时向对方各发一个出站 UDP 数据包。每一方的路由器都会打开一条出站映射。每一方的第一个数据包很可能会被丢弃,因为对方的路由器还没来得及打开映射,但第二个数据包就有地方可去了。从那一刻起,两台路由器都认为自己转发的是一段正常的出站对话,而两台设备就直接对话了。

这叫做 UDP 打洞。它有点神奇,文档完备(RFC 5128),并且适用于现实中绝大多数消费级 NAT。剩下的情况,如对称型 NAT、CGNAT、企业防火墙,正是 TURN 之所以存在的原因。

打洞并不是取巧的办法。它恰恰是 NAT 设计所围绕的明确约定:出站数据包创造入站许可。点对点应用只是有意地发出了那个出站数据包。

STUN:“我的公网地址是什么?”

打洞有一个前提:每一方都必须知道自己面向公网的地址,这样才能告诉对方该把数据包发到哪里。这个地址从设备内部是看不到的。你的 iPad 看到的是它本地的 Wi-Fi 地址(192.168.1.42)。而路由器改写数据包之后,互联网其他部分看到的则是完全不同的东西。

STUN,即NAT 会话穿越工具(Session Traversal Utilities for NAT,RFC 5389),是解决这个问题的小型协议。它的流程简单得几乎让人不好意思:

  1. 对等方向一台公共 STUN 服务器发送一个 UDP 数据包。(Remio 同时使用 Cloudflare 和 Google 的公共 STUN 服务器,以保证冗余。)
  2. STUN 服务器从线路上读取源 IP 和端口,按定义,这就是该对等方经 NAT 转换后的公网地址。
  3. STUN 服务器把这个地址作为负载回复回去:“据我所见,你是 203.0.113.42:48291。”
  4. 对等方现在就知道该向对方公布哪个地址了。

这个面向公网的地址,在 ICE 术语里叫做服务器反射候选地址(server-reflexive candidate)。它的成本几乎为零:连接建立期间多一次往返,连接建立之后则没有任何带宽或延迟开销。STUN 唯一的任务,就是让两个对等方互相认识;一旦它们开始通信,STUN 服务器就再无作用。

TURN:打洞失败时

打洞对大多数 NAT 有效,但并非全部。失败的情况是真实存在的,假装它们不存在的点对点应用,会让相当一部分用户根本连不上。

主要的“反派”:

对于这些情况,回退方案是 TURN,即“绕过 NAT 的中继穿越”(Traversal Using Relays around NAT,RFC 5766)。TURN 服务器是一台双方都能访问到的中继,因为它有一个始终接受入站流量的公网地址。每个对等方都向 TURN 服务器发起一条正常的出站 TLS 连接(任何 NAT 都会放行),再由服务器在双方之间转发字节。

TURN 是有真实成本的。每一个视频数据包都必须多经过一跳网络。在区域性的 TURN 中继上,这会增加大约 30 到 80 毫秒的往返延迟。跨区域的话,比如一个对等方在东京、另一个在圣保罗,却用法兰克福的中继,延迟可以达到 80 到 200 毫秒。TURN 的运营方还要为带宽付费:你串流的每一个比特,都要经过它们的管道。

这就是为什么设计良好的应用只在打洞已确定失败时才使用 TURN。ICE 会自动处理这一决定。

ICE:并行尝试每一个候选地址

交互式连接建立(Interactive Connectivity Establishment,RFC 8445)是把这一切串联起来的编排。ICE 不会预先选定策略。它会为每个对等方收集所有可能的候选地址,把完整列表与对方交换,然后让双方的协议栈并行探测每一对候选地址,竞速找出第一对能通的。

对于每个对等方,ICE 通常会收集:

两个对等方通过一条信令通道交换这些列表,对 Remio 来说,那是一条通往 relay.remio.net 的小型 WebSocket 连接,它承载 ICE 候选地址和 WebRTC 会话描述(SDP),一旦媒体开始流动,它就没有别的事可做了。

两份列表齐备之后,ICE 开始连通性检查。每个对等方沿着每一对候选地址,按优先级顺序发送 STUN 绑定请求数据包。优先级的设计,是为了优先选择延迟最低的路径:

  1. 主机对主机:双方位于同一个本地网络。这是理想情形:几百微秒的延迟,不涉及任何路由器。
  2. 主机对服务器反射,或服务器反射对服务器反射:双方位于不同网络,各自通过自己的 NAT 打洞连通。这就是“互联网上的点对点”在实践中通常的含义。
  3. 任何涉及中继的路径:最后的手段,只有在更高优先级的路径都未通过连通性检查时才使用。

第一对双向都成功的候选地址,会被提名为胜出者,媒体随即沿着这条路径开始流动。整个过程通常在远不到一秒的时间内完成。

ICE 还会持续收集候选地址。如果会话中途出现了更好的路径,比如你的手机离开蜂窝网络、连上了 Wi-Fi,ICE 可以重新提名新路径,而不会中断通话。

为什么 Remio 极力偏好点对点

Remio 是远程桌面应用,而不是视频通话。延迟预算极其严苛。要让会话感觉像坐在主机前,整条管线,也就是采集、编码、网络、解码、渲染,都必须极其短:在局域网上约耗时 8 ms,其余是你的显示器自身 60 Hz 的刷新节奏(每帧约 16.7 ms)。每多一跳,都是罪过。

在直接的局域网点对点连接上,这份预算中网络部分的往返时间约为 1 到 5 毫秒。没有中继,字节直接从一台设备传到另一台。借助 Remio 的管线,这合计为局域网上约 8 ms 的处理延迟(内部实测;其余是你的显示器自身 60 Hz 的刷新节奏),你的输入赶在下一帧绘制之前就已到达。远程机器用起来与本地机器毫无二致。

在经 TURN 中继的连接上,即便是区域性的,网络部分也会跳升到 30 到 80 毫秒。用户感知到的总延迟此时是 40 到 100 ms。对大多数工作来说仍然可用,但在快速拖动或连续快速点击时你能感觉到。触控板不再那么像是你自己的了。

这个差距,就是我们不惜大费周章,把会话保持在点对点路径上的原因。Remio 的 WebRTC 协议栈会同时收集 IPv4 和 IPv6 候选地址,并行访问多台 STUN 服务器,并在 ICE 选择候选地址对时,积极偏好直接路径。在内部,我们甚至用实测的连接往返时间来判定网络类型:低于 15 ms,我们就知道这是局域网,编码器会从高码率起步,并被允许使用多得多的带宽。更慢的则按广域网处理,调优得更保守。

而且,这一点是竞争对手常常悄悄略过的:无论走哪条路径,连接都是端到端加密的。你的屏幕从不会经过我们的服务器,即使是 TURN 中继看到的也只是密文:密钥在握手期间、任何像素移动之前,就已在两个对等方之间直接协商完毕。不论字节是点对点流动还是经由 TURN,Remio 的信令服务器和 TURN 运营方都无法读取它们。点对点只是意味着数据路径上根本没有任何第三方。

中继不可避免时(这也没关系)

有时候,网络之神就是不同意。两端都是对称型 NAT,运营商的蜂窝网络叠了两层 CGNAT 又遇上严格的 ISP,或者企业防火墙只允许出站 TLS 访问已知的云服务商,这些都是真实而常见的配置。在这些情况下,会话要么走中继,要么就根本建立不了。

Remio 的 TURN 后端是 Cloudflare Calls,它为我们提供了一张靠近大多数用户的全球中继网络。当 ICE 选定中继路径时,体验会从“感觉像在本机”降到“感觉像 Splashtop”:依然非常好用,但你能分辨出来。区域性中继增加的延迟为 30 到 80 ms;跨区域则可能达到 200 ms。

重要的是:数据依然是端到端加密的。Cloudflare 看到的,是往一个方向去的加密 UDP 数据包,和往另一个方向去的加密 UDP 数据包。它可以为计费统计字节数,却看不到你的屏幕、你的按键,或你会话的任何内容。Remio 一侧同样没有解密点,因为管线里没有 Remio 的云:我们通过 Cloudflare 运营 TURN 服务,从不触碰其中的负载。

这正是我们的安全白皮书更详细描述的架构。长话短说:无论点对点还是中继,威胁模型都是一样的。

IPv6 这条退路

IPv6 拥有约 3.4 × 1038 个地址,足以给地球上的每一粒沙子都分配一个公网 IP,还绰绰有余。在纯 IPv6 的世界里,NAT 基本没有必要。两台支持 IPv6 的设备可以直接向对方的地址发送数据包,唯一的障碍只是两端各自的主机防火墙。

如果你家里和蜂窝运营商都支持 IPv6,你可能已经注意到,当两端都是 IPv6 时,有些应用连接得更快,那是因为整套“收集候选、探测配对”的流程障碍更少。没有需要发现的 NAT 转换,不需要 STUN 的往返,只有直接的地址。

但有个问题:到了 2026 年,全球的部署依然不完整。许多家用路由器对 IPv6 支持得很差,或者根本不支持。许多企业网络默认阻断入站 IPv6。有些运营商在无线侧提供 IPv6,却在别处桥接到 IPv4。纯粹的 IPv6 到 IPv6 路径是存在的,但不能作为唯一的机制来依赖。

所以 Remio 和每一个正经的点对点协议栈一样,同时收集 IPv4 和 IPv6 候选地址,让 ICE 来竞速。如果存在可用的 IPv6 直连路径,它通常会在延迟上胜出;如果没有,就由带打洞的 IPv4 接手;如果两者都失败,就走中继。用户完全看不到这些,连接就这么建立了。

如何知道你的会话正在用哪条路径

好奇你的会话最终走了哪条路径?Remio 的连接指示器会用通俗的语言显示类型:点对点显示“直连”,TURN 显示“中继”。开发者统计面板则会展示完整的 WebRTC 状态,包括被提名的那一对候选地址的类型(host、srflx、relay)和实测往返时间。

几个简单的解读:

如果你即使在家里也总是回退到中继,常见的“嫌疑人”有:做了对称型 NAT 的运营商调制解调器,你家宽带上的 IPv4 CGNAT(在光纤转售商那里比你想象的更常见),或是过于积极地阻断入站 UDP 的防火墙。我们的降低远程桌面延迟指南逐一梳理了常见的原因,而如果两台设备都在你的网络里,局域网直连页面就是捷径。

真实环境的性能数据

把这些综合起来,下面是我们在生产环境中,对 Remio 会话可能走的不同路径所测得的延迟数据:

这些与 Remio 的性能基准中的数字一致,也解释了为什么我们把局域网与广域网的界限设在 15 ms 往返时间:它能把直连路径与任何中继(最低 30 ms)或蜂窝路径(最低 40 ms)清晰地区分开,误判极少。

NAT 穿透是这样一类主题:单个协议很简单,但组合起来却错综复杂。大多数用户永远不需要知道 ICE、STUN 和 TURN 的存在,他们只会体验到一个能从任何地方快速连到任何地方的应用。当你注意不到这些协议时,它们才是在尽职尽责。而当你确实注意到了,比如会话建立得慢了一拍,或者“直连”变成了“中继”,你现在就有了这套思维模型。

想进一步了解 Remio 的原生管线,以及那些把 1–5 ms 的网络延迟变成约 8 ms 处理延迟(其余是你的显示器自身 60 Hz 的刷新节奏)的选择,请阅读为什么原生很重要。关于中继路径的威胁模型,请参阅安全白皮书。或者直接浏览功能并下载 Remio,亲身体验它的工作。

✦常见问题

常见问题解答

什么是 NAT 穿透?
NAT 穿透是点对点应用用来在两台设备之间建立直接连接的一套技术,这两台设备各自位于家庭或办公室的路由器之后。由于路由器会把许多私有 IP 地址转换为一个公网 IP(网络地址转换,即 NAT),传入连接默认会被阻止。NAT 穿透(主要是 ICE、STUN 和 TURN)会发现每台设备面向公网的地址,在两台路由器上打开一条临时通路,只有当直接打洞失败时,才回退到中继服务器。
STUN 是如何工作的?
STUN(NAT 会话穿越工具)是一种小型的请求-响应协议。客户端向一台公共 STUN 服务器发送一个 UDP 数据包,服务器则回复它在线路上实际看到的源 IP 和端口,也就是公共互联网所见的、客户端经 NAT 转换后的地址。客户端再通过信令通道向对等方公布这个地址,让对方知道该把数据包发往何处。STUN 本身在连接建立期间只增加大约一次往返的延迟,之后没有任何开销。
STUN 和 TURN 有什么区别?
STUN 只是告诉每个对等方自己的公网地址,好让它们尝试直接连接。TURN 则是在直接连接无法建立时,真正通过云端服务器转发媒体。STUN 基本不增加延迟或带宽成本;TURN 多出一跳,区域性中继大约增加 30 到 80 毫秒的延迟,并消耗服务器侧的带宽。设计良好的点对点应用会先使用 STUN,只在必要时才回退到 TURN。
为什么我的远程桌面会回退到中继?
当一端或两端位于对称型 NAT、运营商级 NAT(蜂窝网络中很常见),或者阻断所需 UDP 流量的严格企业防火墙之后时,直接的点对点打洞就会失败。这时应用会回退到 TURN 中继,让连接依然可用。会话依然是端到端加密的,中继看到的只是不透明的加密数据,但区域性中继会增加 30 到 80 毫秒的延迟,跨区域则最多增加 200 毫秒。
WebRTC 中的 ICE 是什么?
ICE(交互式连接建立)是把所有地址发现技术组合起来、并行尝试的框架。每个对等方收集一份候选地址列表,包括本地网络(host)、通过 STUN 获得的公网地址(server-reflexive),以及经 TURN 中继的地址,然后与对方交换这份列表。双方的协议栈沿着每一对候选地址同时发送探测数据包,第一对成功的胜出。优先级更高的候选地址(先是 host,再是 server-reflexive,最后是 relay)会被优先选择,所以在可行时,延迟最低的路径会被选中。
IPv6 能让 NAT 穿透变得不再必要吗?
大体上可以:IPv6 给每台设备一个可路由的公网地址,所以两个支持 IPv6 的对等方无需转换就能直接连接。但到了 2026 年,仍有很大一部分家庭和移动网络只支持 IPv4 或是双栈,而且许多防火墙默认阻断入站 IPv6。因此 NAT 穿透仍然是必需的回退方案,大多数生产环境的应用会同时收集 IPv4 和 IPv6 候选地址,让 ICE 选择连通最快的那条路径。
Remio 应用图标

感受直连路径。

Remio 让每一个候选地址竞速,找出通往你机器的延迟最低的路线:无需端口转发,无需 VPN,无论点对点还是中继,都是端到端加密。

免费使用无需账号30 秒完成配对