avatar

目录
STUN内网穿透原理

STUN内网穿透原理

🧑‍💻 User

nat stun是啥 为啥能行?

🤖 Assistant

你感到困惑是非常正常的。因为光看这几步,你可能会想:“我知道了自己的公网 IP 又怎样?外面的数据包想进来,NAT 路由器不是依然会拦住它吗?

要理解 STUN 为什么有用,我们需要跳出这张图,看一看后续发生了什么

我们可以把 STUN 的作用拆解为三个阶段:照镜子、打招呼、钻洞


1. 照镜子(Discovery:发现自己是谁)

这是你图中显示的部分。

  • 问题: 你的电脑只知道自己的私网 IP(比如 192.168.1.5),它不知道自己在互联网上“长什么样”。
  • STUN 的作用: 它像一面镜子。你给 STUN 服务器发个包,服务器回信说:“嘿,我看你穿的衣服(公网IP)是 120.70.39.4,你的纽扣(端口)是 5001。”
  • 结果: 你的电脑现在知道自己的“公网外壳”了。

2. 打招呼(Signaling:告诉对方我在哪)

这一步是图中没画出来,但至关重要的。
假设你想和你的朋友(Device B)进行视频通话:

  • 你通过一个第三方服务器(比如微信服务器、Zoom 服务器,这叫信令服务器)发个消息给朋友。
  • 消息内容是:“喂,我想跟你连线,我的公网地址是 120.70.39.4:5001,你直接往这个地址发数据吧!”

3. 钻洞(Hole Punching:核心原理)

这是最神奇的地方。为什么对方发数据到这个地址,NAT 路由器就会放行呢?

  • NAT 的特性: 当你的电脑给 STUN 服务器发送请求时,你的 NAT 路由器会在它的“记录本”上记下一行:

    “本地 192.168.1.5:8888 的人 刚才通过公网 120.70.39.4:5001 给外面发了数据,如果有回信传到这个公网端口,我就把它转交给那个人。

  • 维持“洞口”: 虽然这个记录原本是为 STUN 服务器准备的,但在大多数常见的 NAT 类型(比如锥形 NAT)中,这个“洞”一旦打好,任何外网的人(包括你的朋友)只要往这个公网端口发数据,NAT 路由器都会认为这是“回信”,从而准许通过。


用一个生活中的类比

想象你在一个管理很严的大公司上班,公司有围墙(NAT),外人进不来。

  1. STUN(查号码): 你给外面的一个“查询台”打电话。查询台的来电显示看出了你的分机转接出去后的外线号码是 010-8888
  2. 告知对方: 你发短信给你的客户(朋友):“你要找我就打 010-8888,我现在正守在电话旁。”
  3. 钻洞: 因为你刚刚才用这个外线打过电话,公司的总机房(NAT 路由器)在短时间内会保持这个线路处于“激活”状态。
  4. 通话: 客户打过来,总机房一看:“哦,这个外线刚才那个小王用过,可能是客户回电”,于是就把电话转接给了你。

这就是 P2P(点对点)连接成功的关键。


但是!STUN 不是万能的

如果你的 NAT 路由器非常死板(叫做 对称型 NAT / Symmetric NAT,常见于大型企业内网):

  • 它会规定:你刚才打给 STUN 服务器的洞,只能由 STUN 服务器回信。如果别人(你的朋友)想从这个洞进来,NAT 会直接拒绝。

在这种情况下,STUN 就失效了。这时就需要 Workaround 2:TURN(中继服务器)。TURN 就相当于:“算了,洞钻不开,我们找个中间人,我把数据发给中间人,中间人再转交给你。”

总结

STUN 之所以行得通,是因为它利用了 NAT 允许“回信”通过的机制。它先帮你探测出这个“回信通道”的公网坐标,然后你把这个坐标告诉朋友,让朋友伪装成“回信的人”把数据发给你。


🧑‍💻 User

所以就是故意暴露个公网Port任何人都能暂时发这个Port?


🤖 Assistant

你的理解已经非常接近核心了!但关于“任何人”这一点,取决于你家路由器的“脾气”(即 NAT 的类型)。

我们可以把这个过程细化为三个关键点:

1. 是的,你在路由器上“骗”出了一个洞

正常情况下,NAT 像一堵墙,外面的人主动敲门,它是不会开的。
但是,当你通过 STUN 给服务器发包时,路由器会想:“由于里屋的人(你的设备)主动给外面发了消息,我得在墙上开个临时的小窗口(Port),万一外面有回信,我好传回来。”

STUN 的精髓就是:利用这个“回信窗口”来做点对点(P2P)通信。


2. 真的是“任何人”都能发吗?(这是关键)

这就是 NAT 复杂的地方。根据安全级别,路由器对这个“小窗口”有不同的限制:

  • 最宽松的情况(全圆锥型 NAT):
    确实如你所说,只要你的电脑通过 STUN 测出了公网 IP 和端口,世界上任何一个人只要往这个端口发包,你的电脑都能收到。这种最容易实现 P2P。

  • 稍微严格一点(受限圆锥型 NAT)—— 最常见:
    路由器会看一眼来信人的 IP。它会想:“里屋的人刚才只给 STUN 服务器(IP_A)发过信,如果现在有个陌生人(IP_B,也就是你的朋友)发信进来,我要不要拦住?”
    解决方法: 你不仅要用 STUN 测地址,你还得主动给你朋友的 IP 发一个包(哪怕这个包会被对方的防火墙拦截也没关系)。一旦你主动发过包,你的路由器就会把你的朋友列入“白名单”,他发进来的包就能通过那个 Port 进来了。

  • 最严格的情况(对称型 NAT):
    这种路由器非常死板。你给 STUN 服务器发包时,它开一个 Port;当你给朋友发包时,它会另外开一个全新的、不同的 Port
    这时候 STUN 就彻底没戏了,因为你告诉朋友的那个 Port,仅仅是给 STUN 服务器专用的。


3. “暂时”是多久?(Keep-alive)

你说得对,这个 Port 是临时的。如果长时间没有数据往来,路由器为了节省资源,会把这个映射关系删掉,洞就“堵上”了。

所以,为了让这个洞一直开着,应用程序(比如微信、腾讯会议)会每隔几十秒发一个极其微小的包(俗称 “心跳包” / Heartbeat),其目的就是告诉路由器:“这个洞我还在用,别把它关了。”

总结一下你的疑问

  • 故意暴露: 是的,为了让对方能连上你,必须在 NAT 墙上凿开一个公网可见的端口。
  • 任何人: 在多数家用路由器上,经过“打洞”操作后,确实允许特定的对方(或者任何人)访问。
  • 暂时: 是的,必须通过持续的“心跳”来维持这个映射。

这就是为什么 P2P 下载(如迅雷、BitTorrent)或者腾讯会议、Zoom 能够不通过昂贵的服务器中转,直接让两台电脑互传数据的原因。


评论