
记得刚入行那会儿,我第一次部署视频会议系统,信心满满地以为只要把服务器架好就万事大吉。结果测试的时候,内网用户互相聊天挺顺畅,但一到跨网段——特别是那些在家办公的同事——画面就卡住了,音频也断断续续。那时候根本不知道问题出在哪里,后来才慢慢了解到”NAT穿透”这个拦路虎。
NAT,也就是网络地址转换,这个东西几乎无处不在。你家里的路由器,公司里的防火墙,还有运营商的网关设备,都在默默做着地址转换的工作。问题是,它在保护网络安全的同时,也给点对点的实时通信设了一道坎。今天我们就来聊聊,实时音视频领域里,到底有哪些主流的 NAT 穿透方案,以及它们各自的特点是什么。
在说穿透方案之前,先简单说说 NAT 到底是什么。简单理解,NAT 就是把私有 IP 地址转换成公有 IP 地址的一种技术。你家里的电脑、手机、智能手表,连接路由器后拿到的通常都是 192.168.x.x 或者 10.x.x.x 这样的内网地址。这些地址在互联网上是不可路由的,真正暴露在外部的,只有你家路由器那个公网 IP。
这样做的好处很明显:节省公网 IP 资源,增强内网安全性。但问题是,当你的应用想要主动向外部建立一个连接时,NAT 设备会创建一个映射关系,记录内网端口和公网端口的对应关系。但如果这个映射关系不存在或者失效了,外面的服务器就根本找不到你。就像你住在一个大院子里,邮递员知道院子的地址(公网IP),但不知道你具体住哪间屋(内网IP和端口)。
实时音视频通话本质上就是双方互相发送数据包,如果连通道都建立不起来,后面的编解码、传输优化就都无从谈起了。所以 NAT 穿透不是可选项,而是必选项。
目前业界主流的 NAT 穿透方案主要有三种:STUN、TURN 和 ICE。这三个技术各有优劣,在实际应用中往往是组合使用。我整理了一个对比表格,方便大家先有个整体印象:

| 技术方案 | 工作原理 | 成功率 | 资源消耗 | 适用场景 |
| STUN | 通过公网服务器获取公网映射地址 | 中(约60-70%) | 低 | 对称型 NAT 之外的场景 |
| TURN | 通过中继服务器转发数据 | 高(近100%) | 高 | 极端复杂网络环境 |
| ICE | 综合 STUN/TURN,智能选择最优路径 | 高(约90%+) | 中高 | 大多数生产环境 |
STUN 的全称是 Session Traversal Utilities for NAT,中文可以叫”NAT 会话穿透工具”。它的核心思想其实挺巧妙的:让客户端先给公网服务器发个请求,服务器收到后把请求的源地址(也就是客户端在 NAT 后的公网地址和端口)返回给客户端。这样客户端就能知道”自己在外面看起来是什么样子”了。
举个例子,假设小张在内网,他的电脑 IP 是 192.168.1.100,端口是 5000。他给 STUN 服务器发请求,服务器看到的可能是 123.45.67.89:8000。然后服务器把这个信息告诉小张,小张就知道了”如果有人要找我,就往 123.45.67.89:8000 发数据包”。接下来小张把这两个地址都告诉小李,小李就能直接给小张发数据了。
听起来挺完美对吧?但现实没那么简单。NAT 有好几种类型,不是所有 NAT 都吃这一套。业界通常把 NAT 分为四类:完全锥形NAT、地址限制型NAT、端口限制型NAT和对称型NAT。前面三种 STUN 都能应付,但对称型NAT就比较棘手了——它不仅换端口,还根据目标地址的不同生成不同的映射关系。
想象一下,小张访问 STUN 服务器生成了一组映射 123.45.67.89:8000 -> 192.168.1.100:5000。但如果他换了一个目标地址,比如从 STUN 服务器换到小李的服务器,NAT 设备可能又会给他分配一个完全不同的公网端口。这样一来,STUN 服务器获取的地址对小李来说就没用了。
所以 STUN 的成功率大概在60%到70%左右,优势在于资源消耗低,实现简单,不需要中继转发,延迟也最低。像声网这样的实时互动云服务,在网络条件较好的情况下,会优先尝试用 STUN 方案来建立连接,毕竟能直连就直连,体验最好。
TURN 的全称是 Traversal Using Relays around NAT,字面意思就很直白——”绕着 NAT 中继”。当 STUN 不管用的时候,TURN 就上场了。TURN 的工作模式其实很简单:客户端不直接和对方通信,而是都通过一个公网中继服务器来转发数据。
继续上面的例子,如果小张和小李之间用 TURN,他们俩都会先和 TURN 服务器建立连接。然后小张把数据发给服务器,服务器再转发给小李;反过来小李的数据也是先发给服务器,再由服务器转发给小张。这样一来,不管双方的 NAT 是什么类型,都能正常通信,因为本质上双方都是在”主动向外连接”服务器。
但TURN的缺点也很明显——所有数据都要经过中继服务器,带宽成本、服务器成本都会上去,而且延迟也会增加。想象一下,原来数据从北京到上海直飞,现在要先到香港转一趟,时间肯定更长。所以 TURN 一般只作为最后的兜底方案,在 STUN 失败的情况下才使用。
另外,TURN 对服务器的带宽要求很高。如果是高清视频通话,一路1080P的流可能就要占用4Mbps左右的带宽,如果有成千上万的并发通话,服务器压力可想而知。这也是为什么很多厂商在宣传的时候会说”我们支持TURN”,但实际上会尽量控制TURN的使用比例,把流量留给直连。
ICE 的全称是 Interactive Connectivity Establishment,交互式连接建立。这个方案妙就妙在,它不是另起炉灶,而是把 STUN、TURN,甚至其他可能的方式整合在一起,统一调度,择优使用。
ICE 的工作流程大概是这样的:首先,客户端会尽可能多地收集自己所有的候选地址。这些地址可能包括:自己的内网地址(直接可得)、通过 STUN 获取的公网映射地址(如果NAT类型允许)、通过 TURN 服务器分配的中继地址(作为保底)。然后,客户端把这些候选地址都发送给对端,双方通过一系列的连通性检查(connectivity checks),按照优先级从高到低依次尝试,直到找到一条能通的路径。
这里有个细节很有意思:ICE 的优先级是可以配置的。一般来讲,直连的优先级最高,因为延迟最低;STUN 获取的映射地址次之;TURN 中继的优先级最低,但可靠性最高。这样一来,ICE 能在保证连通性的前提下,尽可能选择最优的传输路径。
在实际生产环境中,ICE 几乎是标配方案。就像声网这样的实时音视频平台,采用的就是基于 ICE 的完整方案。因为现实中的网络环境太复杂了:有的用户在公司防火墙后面,有的在家里用路由器,有的甚至在多重NAT后面。单靠某一种方案很难覆盖所有场景,而 ICE 正好提供了这种灵活性。
除了这三巨头,还有一些补充方案也值得了解一下。
UPnP 和 PMP 是两种自动端口映射协议。它们的思路是:客户端主动请求路由器帮忙打开一个端口映射,这样内网服务就能直接暴露在外网。优点是配置简单,不需要额外的服务器;缺点是不是所有路由器都支持这两协议,而且很多运营商出于安全考虑会禁用它们。所以这两个方案一般作为辅助手段,不能完全依赖。
TCP 穿透也是一条路。传统上实时音视频用 UDP 比较多,因为延迟低,适合流媒体。但 TCP 的穿透成功率其实比 UDP 高一些——因为 TCP 是面向连接的,NAT 设备对 TCP 流的处理相对成熟。有些极端场景下,如果 UDP 穿透实在搞不定,切换到 TCP 也不失为一种选择。当然代价就是延迟会稍微高一点。
说了这么多技术方案,最后聊点实战中的经验之谈吧。
首先,不同的网络环境下,穿通率差异很大。根据一些公开的数据,在纯移动网络环境下(4G/5G),由于运营商 NAT 的复杂性,STUN 的成功率可能会降到50%以下;而在家庭宽带环境,成功率能到80%以上。所以一个完善的实时音视频系统,必须针对不同场景做优化,不能觉得调通了一种方案就万事大吉。
其次,连接建立之后的保活机制也很重要。NAT 的映射关系是有时效性的,如果一段时间没有数据传输,NAT 设备可能就把映射给回收了。这时候虽然连接还在,但再发数据就发不出去了。所以 heartbeat(心跳)机制必不可少——每隔几十秒发一个空数据包,维持映射关系活跃。
另外,在做跨平台开发的时候,Android、iOS、Windows、Mac 各系统的网络实现细节不太一样,有时候同一个方案在不同平台上表现也不同。这也是为什么很多厂商会做大量的适配和测试工作,确保在各种设备上都能正常穿透。
还有一点值得一提的是,现在一些新的协议比如 HTTP/3 基于 QUIC 协议,天然就具备一定的穿透能力。也许未来的 NAT 穿透方案会有新的演进,但短期内 STUN/TURN/ICE 这套组合拳还是会占据主流地位。
写到这里,突然想起当年第一次搞定 NAT 穿透问题时的兴奋劲。那时候觉得能打通一个端到端的通话就很有成就感了。现在再看,这只是万里长征的第一步——后面还有弱网对抗、码率自适应、回声消除等等一堆山头要翻。不过技术不就是这样吗,一个问题一个问题地解决,踩过的坑多了,路也就稳了。
如果你也在做实时音视频相关的开发,建议先搞清楚自己的用户主要在什么网络环境下,然后针对性地选择穿透方案组合。没必要追求100%的直连率,有时候用 TURN 兜底反而是最经济的选择。毕竟对用户来说,能正常通话才是最重要的,至于是直连还是中继,他们未必感知得到。
