NAT穿越技术和思路

3

我正在进行 NAT 穿透的过程。

场景如下:我有两部 Android 手机,我想使用 HTTP 服务器(两个设备都在 NAT 后面)将它们连接起来(套接字)。

目前为止,两个客户端连接到 HTTP 服务器,HTTP 服务器记录了它们的 IP 地址和端口。

然而,有一个小问题,因为我使用 Java HttpDefaultClient(),每次从客户端发送请求到服务器时,它都会更改端口。好吧,这听起来像是一个简单的问题:让我们使用 Socket() 来实际维护与服务器之间的有效 TCP 连接。

public Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException

我将使用这个类,并将 localPort 设置为一些我会记住的随机数字。 现在我再重复所有步骤,这次看起来端口不会改变,就像我想要的那样。

现在,在我获取到对手的 IP 和端口(他也在 NAT 后面)之后,理论上我可以断开服务器连接,并使用我已经用于主机客户端服务器的同一 localPort?

除非,现在我有一个问题: 1)如果我关闭 HTTP 服务器套接字,NAT 是否会明白并删除端口映射?(那很糟糕) 2)对称锥形 NAT 是如何传递的? 3) STUN 库是否以某种不同的方式工作?

3个回答

0

对于大多数(但不是全部)NAT,您可以假设存在一些一致性和可预测的端口映射行为。(也就是说,使用相同的本地端口连接到不同的服务器,会映射到NAT上的相同本地端口)。但是,听起来您想在TCP上进行NAT穿透,这比UDP更难。

根本问题是,大多数NAT也充当防火墙。它们不允许来自远程IP:端口的入站连接。我认为诀窍在于同时在两侧进行连接。

您可以在此处阅读有关TCP打洞的更多信息:http://en.wikipedia.org/wiki/TCP_hole_punching


0

NAT并不都是一样的,但你可以确定几件事情: 1)如果你的客户端认为它在X端口上,NAT将把它翻译成另一个端口。 2)NAT通常允许响应出站数据包的数据包进入。

STUN试图通过服务器的帮助猜测实际的出站端口,然后将地址+端口传递给其他客户端。这并不是非常可靠的。TURN则通过服务器路由所有内容。这更加可靠,尽管会在服务器上产生CPU和带宽成本。

如果你可以使用现有的代码来进行NAT穿越,那么你就可以省去很多麻烦。否则,可以通过套接字进行TURN,或者使用类似Urban Airship的东西。我也用过二进制短信,但那是一个特殊情况。


0

我认为您在使用Nats方面遇到了一些问题。事实上,我曾经成功地进行过这样的操作(利用第三方服务器(mine)和公共STUN服务器创建点对点Android连接)。

我极力建议您阅读RFC5389-Nat穿越。这很复杂。我还建议您使用类似JStun库或像我一样实现自己的库。

我只需使用这个类并将localPort设置为随机值,这个值我会记住。现在我要再做一遍,这次看起来端口不会改变,就像我想的那样。

我的猜测是因为您在nat后面,所以您请求的内部端口被映射到了不同的外部端口。

现在,当我有对手的IP&端口(他也在NAT后面)时,理论上我可以断开服务器连接并使用我已经使用过的相同localPort实际托管客户端服务器吗?

目前为止,大多数NAT不仅记录客户端连接的端口,还记录了它们连接到的IP地址,因此它们会阻止来自其他IP的流量。例如,Phone1在IP-a上,并从IP-a的端口-b连接到服务器。NAT将端口-b转换为端口-c。从服务器的角度来看,手机位于IP-a上的端口-c。它将这些信息传递给Phone2。直到Phone1从端口-b向Phone2发送数据,NAT才会阻止所有来自Phone2的通信。

1)如果我关闭HTTP服务器套接字,NAT会理解并删除端口映射吗?(那很糟糕)2)

从经验中学到的一件事是,不要期望从NAT的端口映射行为中得到任何东西,除了你的端口将被映射外,有些NAT会因为你看起来像是愚蠢的原因而更改该映射。这需要大量更新。但总的来说,不会。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接