【问题标题】:What's so hard about p2p Hole Punching?p2p打孔有什么难的?
【发布时间】:2014-06-04 07:14:48
【问题描述】:

我正在尝试一些 p2p 网络。在做一些研究后,我了解到的最大障碍之一是“如果客户端位于 NAT/防火墙后面怎么办”,后来我发现了打孔,但它并不总是能保证工作。

据我了解,我不明白为什么它可能会失败,这是我目前所知道的:



根据上图,这就是我理解如何建立成功连接的方式。
  1. Alice 通过创建与目录服务器的连接来加入网络(1)。发生这种情况时,Alice 的 NAT 会创建一个从她的公共 ip 到她的本地 ip 的映射。
  2. 目录服务器接收连接并将Alice的公共ip:port存储在目录中
  3. Bob 也是如此(2),加入网络并在目录中发布他的ip:port
  4. Alice 想与 bob 交流。于是她从目录中查找 Bob 的 ip:port(3)
  5. AliceBob 的 ip:port 上发送她从服务器获取的数据。 (5)
  6. 由于 Bob 也有一个从 is ip:port 到他的本地 ip:port 的映射,因此 NAT 只会将在 Bob 的 public ip:port 上接收到的任何数据转发给他的电脑。
  7. 同样适用于 Alice
    我希望我在解释我的理解时很清楚。我的问题是,这有什么难的或不可靠的?我一定显然错过了一些东西。你能解释一下它是什么吗?

【问题讨论】:

    标签: networking p2p hole-punching


    【解决方案1】:

    一个问题是 Alice 的 NAT 服务器中的 NAT 映射可能超时,要么在固定时间之后,要么在一段时间不活动之后。

    第二个潜在问题是 NAT 服务器可以限制 Alice 的 NAT 映射仅对 Alice 建立的 TCP 连接或 Alice 与初始 IP“she”之间的连接“良好”连接到。 (换句话说,Alice 和 Bob 之间的直接通信可能被阻止。)

    等等。

    问题在于 NAT 服务器的行为高度依赖于管理组织的配置/策略决策方式。其中许多决定可能意味着您的特定 P2P 使用模式将无法可靠地工作......或根本无法工作。


    那么我关于打孔的整个想法是错误的吗?

    没有。这只是意味着它不会总是有效。

    【讨论】:

    • 很好奇。我相信像 PS3 时代以来的游戏机已经使用了 NAT p2p 打孔。由于防火墙由各方管理,当穿透失败时他们如何解决?您会将 NAT p2p 打孔与集合服务器配对吗?
    • 1) 通常,PS3 的所有者都在为自己的(家庭)防火墙打孔,他们更关注“玩的需要”而不是网络安全。于是他们找到了办法。 2) 对于很多应用程序,中继服务不起作用。
    【解决方案2】:

    NAT 打孔的最大问题可能是缺乏端口一致性。为了使您的实现正常工作,至少两个 NAT 中的一个必须支持它。

    端口一致性是指相同的(local ip, local port) 映射到相同的(external ip, external port),而不考虑目标(destination ip, destination port)。没有这个,目录服务器看到的端口对客户端没有帮助,因为它不是客户端需要相互通信的同一个端口。

    (请注意,这是一个弱于 port preservation 的要求,其中external port == local port。)

    不幸的是,对于 P2P 通信,大多数 NAT 有点类似于Symmetric NAT,并且没有具有一致的端口映射。

    【讨论】:

      【解决方案3】:

      防火墙通常是有状态的。 Bob (2) 与外部目录服务器建立通信在他的 NAT 服务器中设置了一个规则,允许 Bob 和目录服务器进行通信。当 NAT 服务器看到来自 Alice 的数据包时,它会拒绝/丢弃它们,因为它没有看到 Bob 与 Alice 建立通信。

      【讨论】:

        【解决方案4】:

        首先有两种打孔方式 1.UDP打孔 2.TCP打孔

        UDP打孔成功率为82% TCP打孔成功率64% 我做过很多 UDP 打孔实验,大部分都是成功的,但在 TCP 打孔的情况下并不相同。

        TCP打孔失败的原因只是路由器的NAT表。我会尽力解释我最好的:

        客户端 1 --> 连接(客户端 2)--互联网-- 连接(客户端 1)

        现在如果 Client1 **SYN Packet**** 到达 client2 并且 **client2 **SYN packet 没有释放**,client2 的 ROUTER 可以做 2 件事: 1. 当连接被拒绝时,将 RST 数据包发送回 client1。 2. 立即丢弃数据包,没有回复发送给client1。

        如果发生这种情况,将不会建立连接。

        我只能建议一个解决方案,即来自两个客户端的连接调用之间的时间差应该非常小。连接调用差异应该以毫秒为单位

        提示:如果您在本地网络中,请禁用防火墙

        对于 ubuntu 用户:sudo ufw disable

        【讨论】:

          猜你喜欢
          • 2012-07-15
          • 2011-08-19
          • 2011-01-27
          • 1970-01-01
          • 1970-01-01
          • 2016-05-03
          • 2017-04-11
          • 2011-06-14
          • 2018-02-22
          相关资源
          最近更新 更多