8、网络穿透技术:NAT类型详解、STUN协议工作原理、TURN中继服务器部署
聊到WebRTC,有个绕不开的话题——网络穿透。说白了,就是两个设备在不同的局域网里,怎么找到对方并建立连接。我刚开始接触WebRTC时,觉得这步很简单,不就是IP加端口嘛。结果第一次联调就翻车了,两边设备死活连不上。后来才明白,NAT这堵墙,远比我想象的复杂。
8.1 NAT类型详解
NAT(网络地址转换)是路由器用来让多个设备共享一个公网IP的技术。但不同的NAT类型,对穿透的影响天差地别。我个人习惯把NAT分为四种类型,从宽松到严格排列:
| NAT类型 | 特点 | 穿透难度 |
|---|---|---|
| 完全锥形NAT | 只要内网设备发出过请求,外部任何主机都能通过这个映射地址访问它 | 容易 |
| 受限锥形NAT | 外部主机必须收到过内网设备的请求,才能回包 | 中等 |
| 端口受限锥形NAT | 不仅限制IP,还限制端口。外部主机的端口必须匹配 | 较难 |
| 对称NAT | 每次请求不同的外部目标,都会分配不同的端口映射 | 极难 |
关键点:对称NAT是WebRTC穿透的头号杀手。我曾经在一个项目中,80%的连接失败都源于对称NAT。遇到它,STUN基本没戏,必须上TURN。
为什么会这样?你想想看,对称NAT每次发请求都换端口,STUN服务器告诉你的公网地址,下一秒可能就失效了。另一个对端拿着这个地址打洞,就像往移动的靶子上射箭——基本靠蒙。
8.2 STUN协议工作原理
STUN(Session Traversal Utilities for NAT)的作用很简单:帮我找到自己在公网上的IP和端口。但它的工作流程,其实藏着不少细节。
基本流程分三步:
- 客户端向STUN服务器发送Binding Request
- STUN服务器收到请求,看到源IP和端口(这就是NAT映射后的地址)
- 服务器把看到的地址封装在Binding Response里返回给客户端
嗯,这里要注意。STUN不只是拿个地址就完事了。它还能帮你判断NAT类型。我记得有一次排查问题,发现客户端拿到的地址和实际不一致,后来发现是运营商做了二次NAT。这种情况,STUN拿到的地址其实是运营商级的,不是真正的公网IP。
实战技巧:我建议在STUN请求中携带多个属性,比如SOFTWARE属性标明客户端版本,方便后期排查。另外,STUN的Transaction ID一定要随机生成,避免冲突。
STUN的局限性也很明显——它只能帮你拿到地址,不能保证能连通。说白了,它就是个问路的人,路能不能走通,还得看NAT的脸色。
8.3 TURN中继服务器部署
当STUN搞不定时,TURN(Traversal Using Relays around NAT)就上场了。它的思路很简单:既然打不通,那就绕路走。所有数据都经过TURN服务器中转。
部署TURN服务器,我推荐用coturn,这是目前最成熟的开源方案。下面是我常用的部署步骤:
# 安装coturn
sudo apt-get install coturn
# 配置turnserver.conf
listening-port=3478
tls-listening-port=5349
fingerprint
lt-cred-mech
user=webrtc:your_password
realm=yourdomain.com
total-quota=100
bps-capacity=0
stale-nonce=600
避坑指南:我曾经在生产环境忘了配置realm,结果客户端一直报认证失败。排查了半天才发现是realm没设置。另外,total-quota和bps-capacity一定要根据服务器带宽合理设置,否则容易被流量打爆。
TURN的部署架构,我画了一张图帮你理解:
从图中可以看到,当STUN无法打通时,两个客户端都向TURN服务器申请中继地址。TURN服务器分配好端口后,两边的媒体数据都经过TURN转发。说白了,TURN就是当了个中间人。
性能考量:TURN服务器的带宽消耗是双向的。比如客户端A发1Mbps数据给B,TURN服务器实际消耗2Mbps(收1M,发1M)。我建议按峰值带宽的3倍来规划服务器资源。
部署时还有几个细节:
- 认证方式:生产环境一定要开启lt-cred-mech,使用长期凭证机制。临时凭证虽然方便,但安全性差。
- TLS支持:如果业务涉及敏感数据,建议开启TLS(端口5349)。不过要注意,TLS会增加握手延迟。
- 端口范围:TURN默认使用3478,但中继数据端口是动态分配的。我习惯在配置里固定端口范围,方便防火墙放行。
我的经验:在部署TURN集群时,我会用Keepalived做高可用。两台TURN服务器共享一个虚拟IP,一台挂了另一台自动接管。这样即使单点故障,连接也不会中断。
最后说一句,TURN不是万能的。它解决了连通性问题,但带来了延迟和带宽成本。在实际项目中,我建议先尝试STUN,只有在STUN失败时才回退到TURN。这样既能保证连通率,又能节省服务器资源。
公众号:蓝海资料掘金营,微信deep3321