在 NAT 后面的两台计算机之间建立连接 [英] Make a connection between two computers behind NAT

查看:42
本文介绍了在 NAT 后面的两台计算机之间建立连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 NAT 后的两台计算机之间建立连接.我无法打开任何端口.我想使用一个可以上网并且可以与另外两个人进行交流的经纪人.之后,我想在这两者之间建立一条隧道.我正在使用 Python 并且我正在尝试编写此代理的代码.我该如何开始?

I'm trying to establish a connection between two computers behind NAT. I can't open any port. I would like to use a broker who will be on the internet and who will be able to communicate with the two others. After, I would like to establish a tunnel between those two. I'm using Python and I'm trying to code this broker. How can I begin this ?

推荐答案

你想做的可能的,而且几乎是例行公事(至少对于 UDP).这称为 NAT 打孔.它不适用于世界上的所有 NAT,但它适用于许多 NAT,包括大多数当前家用路由器的大多数设置.

What you want to do is possible, and almost routine (at least for UDP). It's called NAT hole punching. It won't work with every NAT in the world, but it works with many, including most setups of most current home routers.

基本思想是,对于大多数路由器,如果您发送传出数据包,它会将来自同一端点的任何传入数据包转发回您.否则,NAT 根本不起作用,对吧?所以,如果你和我试图同时与彼此的公共地址交谈,我们中的一个人将及时在他的 NAT 中打一个洞"来接收消息.另一个人可能会错过最初的消息,因为他打洞太晚了,但他会收到另一个人发送的下一个回复,然后一切正常.

The basic idea is that, with most routers, if you send an outgoing packet, it will forward any incoming packets from the same endpoint back to you. Otherwise, NAT wouldn't work at all, right? So, if both you and I try to talk to each other's public addresses at the same time, one of us will have "punched a hole" in his NAT in time to receive the message. The other one will probably miss the initial message, because he punched his hole too late, but he'll receive the next reply the other guy sent, and after that, everything is working.

不过,这里有一些技巧.

There are a few tricks here, however.

首先,您需要知道您的公共地址.你能直接看到的是你在 NAT 内的私有地址,所以你需要一个位于 NAT 外的服务器,它可以告诉你你来自哪里.对此有一个标准,称为STUN.您不仅可以自行构建和运行多个免费实现,而且互联网上还有多个开放的 STUN 服务器;谷歌获取更新列表.

First, you need to know your public address. All you can see directly is your private address inside the NAT, so you need a server outside the NAT that can tell you where you're coming from. There's a standard for this, called STUN. Not only are there multiple free implementations you can build and run yourself, there are multiple open STUN servers on the internet; google for an updated list.

至少,你有一个私人地址和你的公共地址,而且你真的想给另一个人全部,而不仅仅是一个.(如果你只给我你的公共地址,结果我们在同一个 NAT 上,我们可能无法互相交谈.)如果你有多个 NIC,情况会变得更加复杂,或者你是在具有多层 NAT 等的公司 LAN 上.但是如果你给我一大堆地址,我怎么知道使用哪个?很简单,我可以尝试从我的每个本地地址连接到每个地址,第一个有效的是我一直使用的地址.我们显然需要为此制定某种协议,以便您可以告诉我其中一个何时起作用,但这可能非常简单.

At minimum, you have one private address and your public address, and you really want to give the other guy all of them, not just one. (If you only give me your public address, and it turns out that we're on the same NAT, we may not be able to talk to each other.) It gets even more complicated if you have multiple NICs, or you're on a corporate LAN with multiple layers of NAT, etc. But if you give me a whole slew of addresses, how do I know which one to use? Simple, I can just try to connect to each of them from each of my local addresses, and the first one that works is the one I keep using. We obviously need some kind of protocol for this so you can tell me when one of them has worked, but it can be dead simple.

另外,请注意,当我在这里说地址"时,这不仅仅是指 IP 地址,而是指 IP 地址加上端口.毕竟,NAT 可以并且确实将端口与地址一起转换,而您在 NAT 中打出的洞"通常是特定于端口的.因此,您需要使用将用于实际通信的相同源端口和目标端口进行协商.(实际上,这里有一些棘手的部分,链接文档对此进行了解释,但现在让我们略读一下.)

Also, note that when I say "address" here, that doesn't just mean IP address, but IP address plus port. After all, NATs can and do translate ports along with addresses, and the "hole" that you punch in a NAT is often port-specific. So, you need to do the negotiation using the same source and destination ports you're going to use for the real communication. (Actually, there are some tricky bits here, which are explained by the linked documents, but let's skim over them for now.)

当打孔不起作用,并且您需要退回到通过服务器进行代理时,您不希望该代码看起来完全不同;你最终不得不把所有的东西都写两次,并且在调试时会遇到很大的问题.幸运的是,有一个标准的解决方案,称为TURN,这使得同行看起来就像他们实际上是在直接交谈甚至在他们通过中继交谈的地方.同样有免费的实现,但当然没有开放的 TURN 服务器供您使用(因为这会花费大量带宽).

When hole punching doesn't work, and you need to fall back to proxying through a server, you don't want that code to look completely different; you'd end up having to write everything twice, and having huge problems with debugging. Fortunately, there's a standard solution for this, called TURN, which makes it look to the peers like they're actually talking directly even where they're talking through a relay. Again there are free implementations, but of course there aren't open TURN servers for you to use (because that would cost a lot of bandwidth).

同时,一旦你知道你的公共地址,你必须告诉我它是什么,反之亦然.显然,我们需要一些旁道来进行交谈,比如一个特殊的介绍人"或大厅"服务器.通常,您将点对点连接作为某些服务器中介连接的分支产生.例如,我们可能一起在一个 IRC 频道,或者一个 XMPP/Jabber 聊天网络,并决定我们想要一个点对点通信(以避免窃听,或共享巨大的电子表格文件,或玩没有大量滞后).

Meanwhile, once you know your public address, you have to tell me what it is, and vice versa. Obviously we need some side channel to talk on, like a special "introducer" or "lobby" server. Typically, you're spawning a peer-to-peer connection as an offshoot of some server-mediated connection. For example, we might be in an IRC channel together, or an XMPP/Jabber chat network, and decide we want a peer-to-peer communication (to avoid eavesdropping, or to share giant spreadsheet files, or to play a game without huge lag).

有一个名为 ICE 的标准将这一切联系在一起;只要我们有一个共享的侧信道和一个 STUN(可能还有 TURN)服务器的列表,ICE 就会让我们尽可能协商点对点连接(如果没有,则回退到 TURN).

There's a standard called ICE that ties this all together; as long as we have a shared side channel and a list of STUN (and possibly TURN) servers, ICE lets us negotiate a peer-to-peer connection if possible (falling back to TURN if not).

ICE 支持是 SIP 和许多其他协议的一部分,因此如果您正在使用这些协议之一的库,您可能只需要找出如何给它一个 STUN 和 TURN 服务器列表,那就是它.如果没有,可能有用于执行 ICE 的库.如果没有,肯定有用于执行 STUN 和 TURN 的库(如果没有,它们都是非常简单的协议),因此您可以在它们之上自己进行协商.

ICE support is part of SIP and a number of other protocols, so if you're using a library for one of those protocols, you probably just need to find out how to give it a list of STUN and TURN servers and that's it. If not, there are probably libraries for doing ICE. If not, there are definitely libraries for doing STUN and TURN (and if there weren't, they're both pretty simple protocols), so you can do the negotiation yourself on top of them.

当然,您不必使用这些标准中的任何一个,但您绝对应该阅读它们的作用以及它们为什么这样做.(另外,请记住,人们现在专门制造路由器是为了让 ICE 更好地工作,而对于您发明的任何不同的东西,情况并非如此.)

Of course you don't have to use any of these standards, but you should definitely read what they do and why they do things that way. (Also, keep in mind that people are now making routers specifically to make ICE work better, and that won't be true for anything different that you invent.)

我已经链接到上面的维基百科文章,因为它们从非常简单的技术工作原理概述开始.对于详细的参考规范、入门示例代码、要使用的库等,有更好的来源,但通常维基百科提供了指向您需要的所有其他内容的链接.

I've linked to Wikipedia articles above because they start off with a pretty simple overview of how the technologies work and the rationale behind them. There are better sources for the detailed reference specifications, sample code to get started, libraries to use, etc., but generally Wikipedia has links to everything else you need.

这篇关于在 NAT 后面的两台计算机之间建立连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆