公众号旧文

为什么向公网建立连接就可以穿透NAT?

作者:胖子阅读 —

为什么内网设备主动向公网服务器建立连接之后,公网就能访问内网了?

例如:

  • Cloudflare Tunnel(cloudflared)
  • SSH Reverse Tunnel(ssh -R)
  • frp
  • RIPE Atlas Probe
  • Tailscale DERP 中继

这些都能做到没有公网 IP、没有端口映射、甚至在 NAT 后面,也能让外部访问到内网设备。

核心原理其实并不复杂,只要理解 NAT 的工作方式即可。

一、NAT 在做什么?

假设家里的电脑地址是:

192.168.1.100

家庭宽带公网 IP 为:

1.2.3.4

当电脑访问百度时:

192.168.1.100:52341
        ↓
路由器 NAT
        ↓
1.2.3.4:60001
        ↓
baidu.com:443

此时路由器会创建一条 NAT 映射记录:

公网连接               内网连接
1.2.3.4:60001  ←→  192.168.1.100:52341

也就是:

发往 1.2.3.4:60001 的数据
转发给 192.168.1.100:52341

路由器会把这条记录保存在 NAT 表中。

二、为什么百度可以回访你?

因为 NAT 表已经存在。

百度收到请求后回复:

baidu.com:443
        ↓
1.2.3.4:60001

路由器查看 NAT 表:

1.2.3.4:60001
对应
192.168.1.100:52341

于是将数据转发回内网电脑。

因此通信可以正常完成。

三、那为什么陌生人无法直接访问你?

假设这时有另一台主机:

8.8.8.8

尝试访问:

1.2.3.4:22

路由器检查 NAT 表,找不到对应记录。

于是直接丢弃数据包。

因为路由器根本不知道这个请求应该转发给哪个内网设备。

这也是为什么没有做端口映射时,公网无法直接访问家庭网络中的设备。

四、理解一个关键事实

很多人以为 TCP 连接是单向的,实际上并不是。

TCP 连接虽然由一方发起,但建立成功后就是双向通信。

例如:

A ─────► B

连接建立之后:

A ◄────► B

双方都可以发送数据。

这意味着,一旦连接建立完成,后续通信不再区分是谁发起的连接。

这正是各种穿透 NAT 方案能够工作的基础。

五、Cloudflare Tunnel 的工作原理

当执行:

cloudflared tunnel run

时,

你的服务器
      │
      ├────► Cloudflare
      ├────► Cloudflare
      └────► Cloudflare

通常会建立多个长期 TLS 连接。

如果查看网络状态:

ss -ntp

经常可以看到:

本机随机端口
        ↓
Cloudflare:443

这样的连接。

此时 NAT 表已经存在。

六、用户访问网站时发生了什么?

用户访问:

https://example.com

请求路径实际上是:

浏览器
    ↓
Cloudflare Edge
    ↓
已建立的 Tunnel
    ↓
你的服务器

注意一个关键点:

Cloudflare 没有主动连接你的服务器

因为:

连接早就已经建立好了

Cloudflare 只是把用户请求发送到那条已经存在的 TLS 连接中。

因此没有新的入站连接,自然也不会被 NAT 拦截。

七、那么这算真正的 NAT 穿透吗?

严格来说,Cloudflare Tunnel、SSH Reverse Tunnel、FRP、RIPE Atlas 这类方案并不是教材中定义的 NAT 穿透。

真正的 NAT 穿透通常指:

  • STUN
  • TURN
  • ICE
  • UDP Hole Punching
  • WebRTC 打洞

例如:

  • 微信语音
  • QQ 电话
  • Teams
  • Zoom
  • Tailscale 直连模式

这些技术会尝试让两台 NAT 后面的设备直接建立连接。

中间服务器仅负责协助建立连接。

建立成功后流量不再经过中继服务器。

八、运维领域常说的穿透 NAT

从严格定义来说并不属于打洞技术,但在运维领域,人们通常把下面这些方案统称为 NAT 穿透:

  • Cloudflare Tunnel
  • SSH Reverse Tunnel
  • FRP
  • RIPE Atlas Probe
  • Tailscale DERP 中继

因为最终效果是一致的,只是实现方式不同。

它们依赖的不是打洞,而是由内网设备主动向公网建立一个长期出站连接,然后利用这条已经建立好的连接进行双向通信。