skip to content
Liu Yang's Blog

NAT 穿透原理与 P2P 组网实践

/ 7 min read

Table of Contents

P2P 组网、局域网游戏联机、远程访问内网设备,这些场景都绕不开 NAT 穿透。本文从原理到工具整理一遍。

NAT 类型

路由器做 NAT 时,在内网 IP:Port 与公网 IP:Port 之间建立映射表。不同 NAT 对这个映射的开放程度不同,直接决定了打洞难度。

NAT1 — FullCone(完全锥形)

一旦内网设备向外发 UDP 包并建立映射,任何外部 IP:Port 都可以通过这个公网端口向内发包。打洞成功率 100%。

NAT2 — IP 限制锥

只有之前通信过的 IP(端口不限)才能通过映射向内发包。

检测方法:用另一个 IP 探测失败,但 STUN 服务器换个端口探测成功。

NAT3 — 端口限制锥

只有之前通信过的 IP + Port 完全匹配才能通过。

检测方法:另一个 IP 或 STUN 服务器的另一个端口探测都失败,但用 STUN 接收过的那个端口探测成功。

NAT4 — 对称 NAT(Symmetric)

同一内网地址向不同目标 IP 发包时,路由器会分配不同的公网端口。打洞极难。

内网 10.0.0.5:51820 -> STUN 服务器 => 公网端口 40123
内网 10.0.0.5:51820 -> 对方主机 B => 公网端口 40125(不同!)

控制服务器告诉对方的端口是 40123,但实际流量到达 B 时用的是 40125,打洞失败。

检测工具

Terminal window
# Windows(图形界面)
# https://github.com/HMBSbige/NatTypeTester
# Linux
pip install pystun3
python -m stun

打洞原理(以 Tailscale 为例)

NAT2 / NAT3 下可以打洞,核心流程:

  1. 双方各自向 STUN 服务器发 UDP 包,得到自己的公网 IP:Port

    • A → 203.0.113.5:40123
    • B → 198.51.100.9:51200
  2. 控制平面(Tailscale 协调服务器)把双方的公网地址互相通知

  3. 双方几乎同时向对方的公网地址发 UDP 包

    • A 发包到 198.51.100.9:51200
    • B 发包到 203.0.113.5:40123
  4. 第一个方向的包会被对方 NAT 丢弃(映射还没建立),但本方 NAT 已为这个目标建了映射

  5. 反方向的包到达时,命中了对方刚建的映射 → 穿透成功

“双方同时打洞”的关键就在这里:两边都先主动发包,让对方的回包能进来。

为何 NAT4 打洞失败

对称 NAT 会为不同目标分配不同端口。STUN 服务器得知的外部端口(40123)和实际发给对方时用的端口(40125)不一致,控制平面传递的信息就是错的,打洞必然失败。

有一些高级方案(端口预测、并发探测)可以在部分对称 NAT 下成功,但成功率不稳定,不作为常规方案。


打洞失败时的中继方案

方案说明
Tailscale DERP官方中继,全球分布,自动回退
Headscale + 自建 DERP完全自托管,适合隐私要求高的场景
Tailscale Peer Relay新功能,支持更灵活的中继路由策略
frp有公网服务器时的轻量级穿透方案
gost万能隧道工具,也可以做端口中继

有公网服务器的情况下(例如国内轻量云、阿里云 ECS),frp 或 gost 都是简单可靠的选择,延迟也更可控。


P2P 组网工具对比

工具打洞能力中继特点
Tailscale强(NAT2/3)DERP / 自建最易用,有官方控制平面
Headscale同上需自建 DERP开源,完全自托管
ZeroTier中等ZeroTier Planet去中心化设计,有官方 Planet
EasyTier中等可自建国产轻量,配置简单
N2N基础supernode老牌方案,资源占用极低
WireGuard需手动配置无内置性能最强,无自动打洞,适合固定公网 IP 场景

局域网游戏联机

局域网游戏通过向 255.255.255.255 广播 UDP 包传播房间信息。问题在于:Windows 只在首选网络接口上发广播,虚拟局域网的接口收不到,所以虚拟组网后搜不到房间。

解决方案:

  • WinIPBroadcast:监听所有全局 UDP 广播包,重发到每个网卡接口
  • EasyN2N:集成了 N2N + WinIPBroadcast,打包好开箱即用

适用场景:Hamachi 替代品、老游戏局域网联机、棋牌类游戏。


UDP 流量接管工具

部分应用(含游戏)不走系统代理,需要虚拟网卡在系统层面接管 UDP 流量:

工具平台说明
tun2socks跨平台将 TUN 接口流量转发到 SOCKS
WintunWindows高性能 TUN 驱动,WireGuard 所用
WinPcap / NpcapWindows数据包捕获,底层级别
gost跨平台多协议隧道,也可接管流量

有中心服务器的游戏(Apex、CS2):只要 UDP 能进代理,基本正常游戏,无需代理 ICMP。

P2P 游戏:需关注 NAT 类型,现代协议大多能做到 NAT1,通常不是瓶颈。


参考