代码之家  ›  专栏  ›  技术社区  ›  TobiHeidi

TCP穿孔(NAT遍历)库还是什么?

  •  33
  • TobiHeidi  · 技术社区  · 15 年前

    我想在C_中进行TCP打孔(NAT遍历)。如果需要的话,可以通过会合服务器完成。我发现 http://sharpstunt.codeplex.com/ 但不能让它工作。理想情况下,我需要一个方法,我给它一个端口号(int)作为参数,在nat上调用这个方法之后(“端口转发”)是可用的。如果该方法只返回一些端口号,而这些端口号在nat上是可用的,那也是可以的。有人用C_做过吗?你能给我举个夏普特技或者别的什么的例子吗?

    6 回复  |  直到 9 年前
        1
  •  18
  •   SilverX    14 年前

    在每个网络场景中,tcp打孔的操作方式与udp打孔类似。例如,如果两个对等点A和B位于不同的NAT之后,则发送给另一个对等点的每个对等点的第一个syn包都会打开一个与其各自NAT中的公共地址相关联的漏洞。如果a到b的第一个syn包在b到a的第一个syn包到达b的nat之前到达b的nat,b的nat会认为a的syn包是主动的,并将其丢弃。然而,随后b_s_rst syn包可以成功地通过a_s nat,因为a_s nat将b的公共地址识别为a已启动的传出会话的目的地。

    所以是的。有可能TCP HolePunch。我不明白为什么有人会这么想。

    另外,您不能手动创建这种类型的bahaviour吗?它不需要依赖于任何特定的协议,只要收集所有所需信息的步骤相同。

    一般来说,TCP打孔(3.2.1)按如下步骤进行:

    客户:A、B 服务器:S

    A使用它与S的连接来请求S的连接 用B S回复了A的私人和公共地址, 同时将a的地址发送给b。

    A和B异步建立输出连接- 相互试探(发送syn包)并 专用地址,来自他们使用的同一端口 同时,他们也在听 在其本地TCP上尝试TCP传入连接 端口。

    A和B等待对其输出的syn-ack响应- 发送syn包或传入连接请求 (同步数据包)。如果连接失败,对等方可以重试 最长超时时间。

    一旦三方握手过程完成, 对等方相互验证。如果身份验证- 操作失败,对等方关闭该连接并等待 另一个连接已成功验证。这个 将使用RST成功验证的连接 传输TCP数据。

    (我知道这不是一个很好的答案,但没有足够的评论空间)。

        2
  •  3
  •   JPelletier    9 年前

    这个问题已经很老了,但是对于任何想找到解决办法的人来说,你应该看看 Open.NAT project 它非常容易使用,并与upnp和pmp nats一起工作!

    假设您要将外部端口1700转发到本地端口1600,您只需执行以下操作:

    var discoverer = new NatDiscoverer();
    var device = await discoverer.DiscoverDeviceAsync();
    await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 1600, 1700, "The mapping name"));
    

    您还可以列出所有现有映射,以便验证端口是否尚未使用。

    var sb = new StringBuilder();
    var ip = await device.GetExternalIPAsync();
    
    sb.AppendFormat("\nAdded mapping: {0}:1700 -> 127.0.0.1:1600\n", ip);
    sb.AppendFormat("\n+------+-------------------------------+--------------------------------+------------------------------------+-------------------------+");
    sb.AppendFormat("\n| PROT | PUBLIC (Reacheable)           | PRIVATE (Your computer)        | Descriptopn                        |                         |");
    sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
    sb.AppendFormat("\n|      | IP Address           | Port   | IP Address            | Port   |                                    | Expires                 |");
    sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
    foreach (var mapping in await device.GetAllMappingsAsync())
    {
        sb.AppendFormat("\n|  {5} | {0,-20} | {1,6} | {2,-21} | {3,6} | {4,-35}|{6,25}|",
            ip, mapping.PublicPort, mapping.PrivateIP, mapping.PrivatePort, mapping.Description, mapping.Protocol == Protocol.Tcp ? "TCP" : "UDP", mapping.Expiration.ToLocalTime());
    }
    sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
    Console.WriteLine(sb.ToString());
    

    还有一篇关于msdn上nat遍历的博客文章: https://blogs.msdn.microsoft.com/ncl/2009/07/27/end-to-end-connectivity-with-nat-traversal/

        3
  •  2
  •   Tyr    14 年前

    听起来你可能把tcp和udp搞混了。TCP是一种面向连接的协议,防火墙和路由器很容易理解,并且需要一个发起程序(客户端)和一个侦听器(服务器)。如果客户机和服务器都在防火墙或nat之后,那么如果不让它们都连接到某个代理服务器(不是防火墙),就无法穿透漏洞。这样做的问题是代理将负责中继其所有通信量。

    从你的问题来看,听起来你对udp打孔更感兴趣,它利用了udp是无状态的而不是面向连接的fat。因此,大多数状态跟踪防火墙都会对udp数据流做出“最佳猜测”,并假设离开给定端口的流量将在同一端口上收到回复,并自动将其路由回去。如果使用一些通道外手段(例如简单地传递地址而不是数据的tcp服务器),两个对等方可以在相同的端口上相互传输数据,那么它们各自的防火墙/nat路由器将打开允许通信量进入的漏洞。

    至于如何做到这一点,这完全取决于您将如何获得对等方的IP地址。一旦你有了它,只需在一个约定的端口上开始传输udp数据包,然后等待回复。

        4
  •  2
  •   Anton    12 年前

    我们建立了一个图书馆 IceLink 它使用ice/stun/turn和完整的nat遍历来实现p2p流。基于stun的穿孔技术适用于大多数路由器在节点之间建立直接连接,而对于“坏”的路由器,连接又回到了基于回合的中继。

        5
  •  1
  •   jgauffin    15 年前

    http://sipsorcery.codeplex.com 有一个工作的眩晕服务器。

    sipsorcery.core->sipsorcery.net->眩晕

        6
  •  0
  •   Ying    15 年前

    我不熟悉你的主题,但我碰巧知道一个开源的p2pvpn,它使用lib来做nat。你可以在这里查看(www.socialvpn.org)。

    祝你好运。