小张在家用WebRTC做视频通话,对方一直黑屏;老李部署的私有IM服务,两个局域网外的用户死活连不上;还有人用开源P2P下载工具,速度卡在10KB/s——查日志,全是connection timeout或no route to peer。这些现象背后,十有八九是NAT在“使绊子”。
NAT不是拦路虎,是老房东
别一听NAT就皱眉。它本意是为了解决IPv4地址不够用的问题:路由器把内网设备(比如你的手机、笔记本)统一映射到一个公网IP上,对外只露“一张脸”。但问题来了——当两台都在NAT后边的设备想直接通信时,它们互相不知道对方的真实出口地址和端口,就像两个租客各自住在不同公寓楼里,门牌号只在楼内有效,出了楼就没人认得。
四种NAT类型,堵法各不同
不是所有NAT都一样。RFC 3489 把常见行为分成了四类:
- 全锥型(Full Cone):最宽松。只要内网设备发过包,外部任意IP+端口都能打进来;
- 限制锥型(Restricted Cone):只允许之前通信过的外部IP回包,端口不限;
- 端口限制锥型(Port-Restricted Cone):必须是同一IP+同一端口才能回;
- 对称型(Symmetric):最严格。每次发包,NAT都会分配新端口,且只认准那个“IP+端口组合”,连自己发的第二条包都可能被拦。
国内家用宽带路由器绝大多数是端口限制锥型或对称型,而企业防火墙往往直接按对称型处理。这时候,纯P2P握手基本没戏。
为什么STUN常常不够用?
很多人第一反应是配STUN服务器,比如stun.l.google.com:19302。它确实能帮你拿到自己的公网IP和映射端口,但仅限于“你能主动往外发包”的场景。一旦对方也是对称NAT,你拿到的地址端口,对方根本没法反向连回来——STUN不解决双向可达性,它只告诉你“你在外面长啥样”,不负责帮你敲开对方的门。
TURN是备胎,但真能救命
当P2P直连彻底失败,TURN就是那个中转站。它不靠双方“见面”,而是让双方都连到同一个公网服务器,由它来转发数据。虽然多了跳、有延迟、占带宽,但胜在稳。配置示例(以coturn为例):
listening-port=3478
tls-listening-port=5349
external-ip=203.0.113.45
realm=example.com
lt-cred-mech
user=testuser:testpass客户端连接时,先走STUN测连通性,失败则自动降级到TURN,整个过程对上层业务透明。
实战小技巧:看一眼你的NAT类型
不用抓包,用命令行快速判断(Linux/macOS):
curl -s 'https://stun.ipip.net/stun.php' | jq .返回里如果有"nat_type":"symmetric",那基本可以放弃纯P2P幻想了。更直观的方法是跑一遍Pion ICE Trickle 示例,观察candidate类型:如果全是relay,说明STUN失效,已 fallback 到TURN。
说到底,P2P连接失败不是技术不行,而是现实网络环境太“实在”——每个NAT都只守好自己那一扇门。理解它的脾气,再选对工具,比硬刚协议细节管用得多。