穿越NAT连接P2P?

58

我开始尝试使用p2p连接与其他人建立联系,因此我在JAVA上编写了一个简单的套接字程序,以便Android设备的用户可以共享简单的p2p消息(当时我对NAT一无所知)。后来我了解到了NAT,现在我需要与另一个使用服务器进行发现的用户建立TCP连接,但有效负载是通过p2p传输的。我还看过XMPP(关于协议如何工作的非常好且详细的解释在这里),以及UPnP,但我不知道如何实现它们。

另一个有趣的问题是BitTorrent,因为它们可以在任何设备上甚至在NAT背后工作。我找不到关于BitTorrent如何工作的任何解释。

我已经做了很多研究,但我被卡住了。

我的问题是:

  1. 一个详细的BitTorrent解释(像这里一样,不是关于怎么下载种子的)以及它如何能够绕过NAT?
  2. 是否有办法通过编程方式创建一个NAT条目?
  3. 套接字编程对于p2p是否足够?
  4. 创建自己的协议有多困难,我该如何构建一个协议?
  5. 如果两个设备D1和D2想要进行p2p通信并且它们知道彼此的IP,则D1向D2发送请求但无法穿过D2的NAT,但应该在D1的NAT中创建一个条目。那么当D2尝试发送一些东西时,D1的NAT应该发现一个带有D2 IP的条目。为什么它不允许数据包通过?

Bittorrent使用UDP打洞技术。我认为在网络上没有任何详细的解释。 - Encombe
@Encombe 我已经了解了关于“打洞”的内容。1. 它并不总是成功的。2. 不能使用UDP传输消息,因为它非常不可靠。 - user3439988
@Encombe,您能告诉我这些协议如何处理动态IP地址吗?手机的IP地址在单个会话中是否保持不变,或者超时时间是多少? - user3439988
我建议你可以在其他客户端的代码中进行一些研究,比如Transmission,并查看它是如何实现的。例如,在这里(https://trac.transmissionbt.com/browser/trunk/libtransmission/upnp.c)。这可能很困难,但我认为这将是有益的。 - paulochf
这是上面提到的XMPP文章链接。该链接已经失效,显示404错误。https://web.archive.org/web/20170204074212/http://ceit.uq.edu.au/content/how-xmpp-works-step-step - Yashas
4个回答

27
另一个有趣的问题是关于BitTorrent的,因为它们可以在任何设备上运行,甚至在NAT后面也可以。我无法得到任何关于BitTorrent如何工作的解释。
这个陈述似乎认为BitTorrent需要完全的连接才能运行,这是不正确的。
在NAT设备后面,您仍然可以建立出站TCP连接。通常情况下,只要网络中有其他非NAT(或已正确端口转发)的客户端可以接受传入连接,这就足以满足BitTorrent的要求。
NAT对数据流方向没有影响,因为一旦建立连接,连接就是双向的。它只会对初始连接设置造成问题。
这对BitTorrent来说非常有效,因为BitTorrent并不关心从哪个特定节点获取数据。尽管更好的连接通常会提高性能。
如果节点的身份很重要或者一对一的转移是一个重要的用例,那么其他点对点协议通常会首先尝试 NAT穿透,如果失败,则依赖于第三方节点在那些不能直接连接的节点之间中继流量。
此外,IPv6支持将成为未来维护端到端连通性的必要条件,因为越来越多的ISP开始推出运营商级NAT以供IPv4使用,而IPv6仍将保持非NAT状态。

1
我的目的是为了弄清楚“初始连接设置”是如何发生的。我知道BitTorrent使用DHT来查找连接。假设您知道目标的IP地址,即使如此,您也无法穿过NAT。因此,您需要某些东西来创建一个条目进入NAT转发表中,以便数据可以流动。您关于数据输出的说法是绝对正确的,您也正确指出在初始连接设置完成后,数据可以毫无问题地流动。 您能否建议我在初始阶段和IP更改时采取什么措施? - user3439988
因此,您需要创建一个条目以便将数据流入NAT转发表中。对于出站连接,本地NAT设备会自动创建这些条目。这就是为什么我说如果远程可达,则出站连接将正常工作。如果这不是您的意思,请在问题中附上更具体的场景,概述两个节点之间的整个路径和您希望执行的操作。 - the8472
我已经在我的回答中涵盖了这些内容,请仔细阅读。 - the8472
我也读到了Bleep使用SIP,但我找不到任何实现。也许你可以帮忙。 - user3439988
1
这是否意味着,如果在BitTorrent网络中没有未经NAT处理的节点,那么BitTorrent将无法工作? - Aditya Agarwal
显示剩余3条评论

16
需要明确的一件事情是,目前在各种类型的NAT之间实现100%的P2P是不可能的。在Symmetric和Symmetric/PRC NAT之间建立P2P连接没有实用的方法,因此需要通过一个名为TURN的中继服务器来建立连接。
我正在回答你的第二个问题,因为我对第一个问题不太了解。
是的,你可以通过你的NAT发送数据包,并且会有一个映射将你的内部IP:Port映射到你的NAT的外部IP:Port。你可以通过发送STUN请求来知道这些外部IP:Port。请注意,这种技术对于对称性NAT无效。
是的,套接字编程足以支持P2P。
既然已经有几个协议存在,为什么还需要一个新的协议呢?ICE协议是目前最好的NAT遍历协议,我认为它不容易创建。UPnP和NAT-PMP在安全方面真的很脆弱。
我认为通常情况下NAT会阻止未知的数据包进入。因此当D1向D2发送数据包时,它的NAT会阻止来自D1的IP:Port的所有传入数据包,这就是连接建立失败的原因。你必须采用打洞技术才能成功地建立D1和D2之间的P2P连接。
**通过对称性NAT,我指的是随机端口分配的对称性NAT。

9

6
  • 最新版本的BitTorrent使用µTP,它位于UDP上层而非TCP。 µTorrent使用一个私有扩展(ut_holepunch)执行UDP打洞,大多数其他实现不会这么麻烦(Tixati是一个值得注意的例外)。

  • 一些NAT路由器使用uPNPPMP协议接受端口转发请求。是否支持取决于特定品牌的路由器及其配置。

  • 是的,套接字编程足以用于P2P。

  • 很难回答。建议您首先阅读经过维基化和注释的BitTorrent规范

  • 是的,这就是UDP打洞背后的原理。


我从你的回答中得出的结论是,除了使用uPNP和PMP之外,使用NAT穿透是唯一的解决方案。这三种方法都不是100%可靠的解决方案。而且uTP在UDP上运行,同样不可靠。BitTorrent制作了一个名为Bleep(P2P聊天)的应用程序。他们使用SIP进行初始化。还有另一个解决方案是使用带有错误处理的UDP来像TCP一样工作。你知道如何实现其中任何一个吗? - user3439988
@Encombe提到了Tixati,因为它在发布说明中,但找不到关于libtorrent的任何信息。您确定它实现了ut_holepunch吗? - jch
4
如果我今天要编写一个P2P应用程序,我会让它纯IPv6,与此同时不考虑其他方面。 - jch
@jch,我想我在pcaps中看到了qBittorrent的ut_holepunch。此外,搜索结果显示:Arvid说:“libtorrent中的holepunching支持始终开启。”这里。您可能需要检查libtorrent源代码以确认。 - Encombe
通过在µT(日志选项卡>对等流量记录>记录holepunch)中激活日志记录,我可以确认Holepunching与BitTorrent / µTorrent、libtorrent(Deluge、qBittorrent、Bitlord)、Tixati和Xunlei兼容。libtorrent源代码 - Encombe
显示剩余3条评论

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