结论: 若 Full Cone = 1, Restricted Cone = 2, Port Restricted Cone = 3, Symmetric = 4, 假设 A 端的 nat 类型代表的数值为 k1 (1 <= k1 <= 4), B 端的 nat 类型代表的数值为 k2 (1 <= k2 <= 4), 根据我掌握的到的计算机网络知识, 只有当 k1 + k2 <= 6 时, A 和 B 才能成功建立 p2p 连接
今天我试了用 easytier 组网, 具体来说, 就是我有台的 MacBook Pro, 一台 Windows, 还有一个阿里云小水管机器, 组网成功后, 我执行了命令查看组网情况, 如下图所示
没错, 符合我预期, MacBook Pro 是 Symmetric = 4, Windows 是 Port Restricted Cone = 3, 4 + 3 = 7 > 6, 只能走阿里云小水管中继
但是 5 分钟后我又执行了命令查看组网情况, 如下图所示
发现了 MacBook Pro 和 Windows 之间是 变成了 P2P 连接
MacBook (priv_ip1, priv_port1)
|
|
公网出口 1 (pub_ip1, pub_port1)
|
...(中间很多路由)
|
阿里云小水管 (aliyun_ip, aliyun_port)
|
...(中间很多路由)
|
公网出口 2 (pub_ip2, pub_port2)
|
|
Windows (priv_ip2, priv_port2)
* case1:
1. Windows 发起请求访问 MacBook 的(pub_ip1, pub_port1) , 但是被拒绝, 这个请求对于 nat4 而言是"陌生请求"(因为 Windows 和 MacBook 之前没有建立连接)
2. 但是这时候能从(pub_ip1, pub_port1)访问 Windows 了 (因为是 nat3, 端口和 IP 都受限, 只能从(pub_ip1, pub_port1)访问, 其它的网段访问 Windows 还是会被拒绝)
3. 这时候 MacBook 再次向(pub_ip2, pub_port2)发起请求, 但是因为 MacBook 是 nat4, 导致分配到的出口路由器的端口不再是 pub_port1, 而是 another_pub_port1 (假设出口路由器不变)
4. 这样访问 Windows 就会被拒绝, 因为对于 Windows 而言, 只允许从(pub_ip1, pub_port1)过来的请求访问, 而从(pub_ip1, another_pub_port1)过来的是没法访问的
* case2:
1. MacBook 发起请求访问 Windows 的(pub_ip2, pub_port2) , 但是被拒绝, 因为是 nat4, 导致分配到的出口路由器的端口不再是 pub_port1, 而是 another_pub_port1 (假设出口路由器不变)
所以这样就没法打洞成功
所有 AI 不能很清楚的回答我的问题, 在我的追问后这些 AI 就难以自圆其说
![]() |
1
ysc3839 6 小时 44 分钟前 via Android
NAT 类型检测错了吧,阿里云服务器怎么可能是 Port Restricted ?没有公网 IP 吗?
|
![]() |
2
ysc3839 6 小时 39 分钟前 via Android
还有一种可能是 Windows 机子用端口扫描的方式,往 Mac 机子 IP 的不同端口都发送数据包,遇到有回应的端口那就是 NAT 分配到的端口
|
![]() |
3
ptg2008 OP @ysc3839 这个我考虑过在 case1 的第 4 步后 Mac 从(pub_ip1, another_pub_port1)访问 windows 的(pub_ip2, pub_port2) 会被拒绝, 但是对于(pub_ip1, another_pub_port1)而言, 可以从 windows 的(pub_ip2, pub_port2) 访问, 因为由 Mac 主动发起了, 不过这个 another_pub_port1 只能靠对端的 windows 去猜 another_pub_port1 的分配规律, 猜中的话就能建立接连, 但是我 rust 不熟练, 等我有空了我看看 easytier 的实现
|
![]() |
4
ptg2008 OP @ysc3839 检测了 他确实是 Port Restricted, 有公网 IP 的
Welcome to Alibaba Cloud Elastic Compute Service ! Last login: Thu Sep 4 15:06:12 2025 from 58.251.160.132 ➜ ~ sudo /opt/easytier/easytier-cli stun stun info: StunInfo { udp_nat_type: PortRestricted, tcp_nat_type: Unknown, last_update_time: 1756978903, public_ip: [ xxxxxx, ], min_port: 58939, max_port: 58939, } |
![]() |
5
xdeng 6 小时 20 分钟前
估计类似于 生日悖论暴力扫描 https://arthurchiao.art/blog/how-nat-traversal-works-zh/
|
6
edcopclub 4 小时 59 分钟前 via Android
在一定范围内扫描端口连接就行了,有概率能正好能连上。
|
7
psllll 4 小时 52 分钟前 via Android
试试用 frp 的 xtcp 模式
可以一直重试直到打洞成功,不会回落走中转 像这样 serverAddr = "" serverPort = natHoleStunServer = "stun.miwifi.com:3478" [[visitors]] name = "" type = "xtcp" keepTunnelOpen = true maxRetriesAnHour = 3600 minRetryInterval = 1 serverName = "" bindAddr = "127.0.0.1" bindPort = 10088 |