p2p穿透
你家里的穿透路由器,大概率没有公网IP。穿透这事十年前不是穿透问题,现在却成了大麻烦。穿透
运营商把IPv4地址省着用,穿透一层层NAT叠下来,穿透你家网络就像住在集体宿舍里——有门牌号,穿透但那是穿透楼里的编号,外面的穿透人根本找不到你。想从外网连回家里的穿透NAS、摄像头、穿透或者自己搭的穿透Minecraft服务器?门都没有。
P2P穿透就是穿透干这个的:让两个都躲在NAT后面的设备,直接说上话。穿透
NAT到底挡了什么
假设你的穿透电脑是192.168.1.100,想连朋友的192.168.1.101。这俩地址在各自局域网里都合法,但放到公网上就是废纸——全球有无数个192.168.1.100,数据包出了路由器就不知道该往哪送。
NAT设备(通常就是你家路由器)做了件事:它把内部地址映射成公网地址加端口。你访问百度,路由器记下“内网192.168.1.100:54321对应公网123.45.67.89:60001”,百度回包时按这个映射转回来。但这条映射是临时的,而且只对百度有效。朋友想主动连你?路由器一看:没人先发过包,这条映射不存在,直接丢弃。
这就是P2P穿透要绕过的墙。
STUN:先搞清楚自己长什么样
最基础的穿透手段叫STUN(Session Traversal Utilities for NAT)。原理不复杂:你找个公网服务器,让它告诉你“你从外面看是什么地址和端口”。
比如你向STUN服务器发个请求,服务器回:“我看到你是123.45.67.89:60001。”你把这个地址告诉朋友,朋友试着往那发数据。如果NAT类型够宽松(比如全锥形NAT),包就进来了,连接建立。
但现实没那么美好。很多路由器是“对称NAT”——你每次向外连不同目标,它都分配不同的公网端口。你告诉朋友的端口,只对STUN服务器有效,朋友发来的包照样被扔。STUN在这里就瞎了。
TURN:实在不行就中转
对称NAT下,STUN没戏。那就别硬穿,找个公网服务器当中转站,两边都连它,它负责转发。这叫TURN(Traversal Using Relays around NAT)。
缺点很明显:带宽全走服务器,延迟高,成本也高。你搭个TURN服务器给几个人用还行,想撑起视频会议或者游戏加速?流量账单能吓死人。所以TURN是保底方案,不是首选。
打洞:同时伸手
真正有意思的是“打洞”(hole punching)。
你和朋友同时向对方的公网地址发UDP包。你的包到了朋友的路由器,虽然它不知道这包该给谁,但发出去的动作本身,在你自己的NAT上开了个洞——路由器记住了“我往朋友IP:端口发过包,回包可以进来”。朋友的包同理。两个洞一开,后续数据就能直接走。
这招对锥形NAT很有效,对对称NAT基本无效——因为你发给朋友的端口,和你发给STUN服务器的端口不一样,朋友按那个端口回,你的NAT不认。
现实里的组合拳
WebRTC、ZeroTier、Tailscale这些工具,基本都在干同一件事:先试直连(STUN+打洞),不行就降级到TURN中转。你感觉不到切换,但底层在疯狂试探。
我自己的经验是,国内运营商网络下,对称NAT比例不低。家里宽带打洞成功率大概六成,剩下四成得靠中转。用Tailscale连家里NAS,有时候延迟20ms,有时候突然跳到200ms——那就是打洞失败,悄悄切到DERP中转了。
P2P穿透不是魔法。它是在NAT的规则缝隙里找路,能找到就直连,找不到就认命走中转。理解这一点,你就能明白为什么有些P2P应用时快时慢,也大概能猜到——哦,今天路由器又犯倔了。
(责任编辑:探索)
