【问题标题】:UDP hole punching for Server/Client communication under NAT with STUN使用 STUN 在 NAT 下进行服务器/客户端通信的 UDP 打孔
【发布时间】:2015-11-04 01:21:40
【问题描述】:

问题

我正在尝试开发一个通信系统,其中:

A,B是NAT下的机器,A是服务器B是客户端 S 是 STUN 服务器

S 正在一台可以通过 Internet 访问的机器上运行

流程如下:

A hits S with an opcode saying he's the server
S registers A as server

B hits S with an opcode saying he's the client
S sends to A B's external infos (IP, PORT)
S sends to B A's external infos (IP, PORT)

A starts sending B an opcode saying he's the server every 500ms
and meanwhile listens for packets saying he's got a client

B starts sending A an opcode saying he's the client every 500ms
and meanwhile listen for packets saying he's got the server


麻烦

这就是麻烦开始的地方,STUN 服务器完成了它的工作,因为两端都收到了关于另一端的正确信息。

但是我从来没有收到另一端的消息,所以两端一直在监听,没有收到握手操作码或其他任何东西。

NAT 的行为

我确实检查了这个 NAT 的行为,看起来确实像这样

A 位于 192.168.X.X,端口 4444 连接到外部暴露 N.N.N.N:4444 因此,只要端口号可用,就会保留端口号,如果不可用,则获取一个新的(随机?)。

测试

我运行的测试看到两端(A、B)都托管在同一台机器上,都绑定到机器的内部 IP,尝试绑定到 127.0.0.1、0.0.0.0,没有任何变化。

如果在他们收听握手时我 echonclocalhost 的东西,它被接收并显示(作为无法识别的消息)没有任何问题。通过 NAT 路由的连接并不难,每个数据包都会被丢弃。

还尝试将 A 托管在机器上,B 托管在移动数据下的 Android 手机上,并使用临时编写的简单应用程序。仍然在等待某些东西,比如 nodejs 测试。


更新: 我尝试做的另一件事是用nc打开一个洞

我在同一 NAT 下的两台不同机器上运行:

echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4567 -p 4568

echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4568 -p 4567

每台机器的时间不同。据我了解,这应该在 NAT 中打一个洞,丢弃第一个数据包并随后转发。但什么也没发生,没有尽头得到消息。

我也试过了:

来自本地机器 echo "GREET UNKOWN PEER" | nc -u <PUBLIC IP> 4567 -p 4568

来自公共机器 echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4568 -p 4567

这个工作,NAT下的本地机器联系公共机器,在第一个丢弃的数据包能够在分配的端口上接收和发送。我想知道为什么这在同一 NAT 下的两台机器上不起作用(???)


代码

我没有显示任何代码,因为我认为这存在某种逻辑缺陷,但这里是 github 项目。

index.js 包含 STUN 服务器,tests 文件夹包含测试用例:test.js 启动 stun 服务器,PeerClientTest.jsPeerServerTest.js 是客户端和服务器的模型。

运行node tests/test.js在公共机器上启动服务器(更改config.jstests/config.js中的IP)

然后node tests/PeerServerTest.js 启动服务器(“A”)和node tests/PeerClientTest.js 启动客户端(“B”)。双方将通过 STUN 相互识别,然后在发送自己的握手操作码的同时监听对方的握手操作码。这种情况永远不会发生,所以他们只会一直发送/收听。

节点不是必需的,所以如果有其他语言的更好的解决方案,请告诉,将不胜感激。

【问题讨论】:

    标签: networking udp nat stun hole-punching


    【解决方案1】:

    B 的 NAT 过滤 A 的数据包,不让它们通过。 NAT 过滤发送给它的未知数据包。您的服务器 A 正在向客户端 B 发送数据包。但客户端 B 之前从未通过 NAT 向 A 发送数据包。因此,对于 B 的 NAT,A 的数据包是未知的并被丢弃。

    您需要在 B 的 NAT 上打一个洞,以便 NAT 允许传入的数据包。从 B 向 NAT 的 IP:Port 发送数据包。之后,当您从 A 向 B 发送数据包时,B 的 NAT 不会丢弃 A 的数据包。

    如果 A 和 B 的 NAT 具有 Symmetric 和 Symmetric/PRC NAT 之类的组合,这将不起作用。在这种情况下,您将不得不使用 TURN 中继服务器。

    【讨论】:

    • 实际上我是这样做的。在 A 和 B 联系 S 之后,他们收到了另一端的地址(NAT IP、PORT),并开始互相发送数据包并监听传入的响应,这意味着洞已经打开。这永远不会发生,他们会卡在发送/等待响应中。
    • B的NAT类型是什么?您写道“A 位于 192.168.X.X,在端口 4444 上连接到外部,暴露 N.N.N.N:4444,因此只要端口号空闲,就会保留该端口号”。你能用B也验证一下吗?您需要知道当 B 向 A 发送数据包时,B 从服务器 S 获得的公共端口是否保持不变。
    • 在我运行的测试中,A 和 B 都托管在同一台机器上,所以相同的 NAT,相同的外部甚至内部 IP,只是端口不同。在具有不同路由器和 ISP 的两个不同网络下尝试使用此配置。还尝试在我的机器上使用 A,在 Android 上的移动数据下使用 B。结果相同。
    • 对于同一个网络,你不需要去 NAT。但是对于不同的 NAT,您需要知道两端的 NAT 类型。每个 NAT 都有不同的行为,对于 NAT 穿越,此信息是必不可少的。在不知道我们无法确定任何事情的情况下。
    猜你喜欢
    • 1970-01-01
    • 2012-08-21
    • 1970-01-01
    • 2020-11-13
    • 2011-04-21
    • 2021-12-20
    • 1970-01-01
    • 2012-04-11
    • 1970-01-01
    相关资源
    最近更新 更多