【问题标题】:forward traffic from port X to computer B with c# "UDP punch hole into firewall"使用c#“UDP打孔进入防火墙”将流量从端口X转发到计算机B
【发布时间】:2011-11-05 17:04:33
【问题描述】:

我需要建立从我家的计算机到我的办公室计算机的 tcp 连接。

在办公室有一个路由器,连接了几台计算机。该路由器有互联网,因此连接到该路由器的所有计算机也有互联网。在我的家里,我有一台可以上网的电脑。我需要我的办公室计算机充当服务器,而我的家用计算机则需要连接到它。以前,我以前可以通过服务器上的端口转发流量进行连接:

    NATUPNPLib.UPnPNATClass upnpnat;
    NATUPNPLib.IStaticPortMappingCollection mappings;

    public ServerExample()
    {
        InitializeComponent();

        upnpnat = new NATUPNPLib.UPnPNATClass();
        mappings = upnpnat.StaticPortMappingCollection;

        //                           server local IP address
        mappings.Add(1300, "TCP", 1300, "192.168.150.146", true, "plsease work");
        // this code tels the router to forward all tcp traffic comming from port
        // 1300 to the server computer (it's lan ip address happens to be 192.168.150.146)
        //...

我能够从我家连接。 (我知道最简单的方法是打开办公室路由器上的端口并将它们转发到我的电脑,问题是我无法访问办公室路由器)

现在他们用更新的路由器替换了我办公室的路由器,我无法使用我的代码。现在,使用新路由器,当我执行我得到的原始代码时:

请注意,映射返回 null;因此,我无法添加映射。

我确信应该有一种方法可以建立连接,因为办公室中的某些人会使用 Limewire 或 bit torrent。我认为我的问题可能与权限有关?我该如何解决这个问题?


编辑

所以从研究中我发现我正在尝试做的是“UDP 打孔进入防火墙”。我实际上想通过 tcp 连接来完成。我不知道 tcp 和 upd puch holing 之间有什么区别......我的意思是,这样做的目的是让客户端能够找到梨,而无需在路由器上进行配置。

.

.

.

.

.

.

更新

好的,所以我相信我已经尝试过用 c# 做你们在这个问题上发布的内容:好的,让我告诉你我做了什么:

请注意,您可能需要参考此图才能理解我将要解释的内容:

如你所知,我想在计算机 A 和计算机 B 之间建立一个 tcp 连接。我设法做到这一点的方法是进行所谓的 tcp 打孔。

第 1 步: 我要做的第一件事就是开始监听服务器 S 上的新连接。

                   TcpListener server = new TcpListener(System.Net.IPAddress.Parse(“192.168.11.109”), 55550);
                   Server.Start();

                   var client = server.AcceptSocket();  \\ wait here until someone connects

第 2 步: 现在用计算机 A 连接到服务器:

          TcpClient tcpClient = new TcpClient("192.168.11.109", 55550);

第 3 步: 在计算机 A 上执行步骤 2 代码后,服务器 S 调试应如下所示:

第 4 步: 现在我们的目标是从计算机 B 连接到计算机 A。服务器 S 拥有 B 建立连接所需的信息。实际上,我必须在计算机 B 和服务器 S 之间建立连接,以便服务器 S 可以为 B 提供适当的参数,以便 B 连接到 A。

第 5 步: 因为我正在调试,所以我可以看到参数,所以我现在通过侦听端口 3313 使计算机 A 成为服务器。我希望计算机 A 现在在该端口(3313)上侦听,因为所有包都通过端口发送到路由器 X应将 3313 发送到计算机 A。

       \\ COMPUTER A 
       TcpListener server = new TcpListener(System.Net.IPAddress.Parse("192.168.0.120"), 3313);
        server.Start();

        var newClient = server.AcceptSocket();  \\ wait here until a client gets connected

第 6 步: 所以计算机 A 现在应该在端口 3313 上侦听新连接。再次,端口 3313 很重要,因为路由器 x 应该将从该端口收到的所有包转发到计算机 A。

计算机 A 正在等待新的连接。

第 7 步: 所以现在快点!我们想从计算机 B 建立连接。实际上服务器 S 将传递参数,但由于我只是想完成这项工作,我将在计算机 B 上快速编写程序。

          TcpClient tcpClient = new TcpClient(“192.168.11.108”, 3313);
           \\192.168.11.108  is the address of router X

最后:

由于某种原因,计算机 B 无法连接到计算机 A。

无法连接的原因是路由器 X 没有将包转发到计算机 A。(我知道这是因为我在路由器 X 上的端口 54540 上启用了端口转发,并且当我使用该端口时它可以工作)我的意思是我不明白为什么路由器 X 没有将来自端口 3313 的流量转发到计算机 A。计算机 A 已经建立了与服务器 S 的连接,并且服务器 S 通过端口 3313 发送到路由器 X 的所有内容都发送到了计算机 A . 为什么如果我通过端口 3313 将包发送到路由器 X,它们不会被计算机 A 接收!?

PS:

请注意,我在这里展示的所有内容,实际上都有三个路由器 X、Y 和 Z,还有服务器 S、计算机 A 和计算机 B:

【问题讨论】:

  • 这通常不是编码问题,而是管理/策略:在大多数组织中,不允许将内部机器暴露在互联网上。如果您愿意这样做,我建议您以友好的方式直接与网络管理员交谈..
  • 是的,如果我联系管理部门,我认为应该获得许可。只是我很好奇,因为我能够使用比特洪流、石灰线和其他 p2p 应用程序。用代码解决这个问题会更好,而不是通过与管理人员交谈,而且我学到了:)
  • 这些协议的工作方式不同...谷歌搜索“UDP 打孔进入防火墙”

标签: c# networking tcp portforwarding


【解决方案1】:

您的新工作路由器可能已禁用UPnP,因此您的引用为空。

如果没有这个,您的服务器将无法对入站流量可见,因为路由器不知道将入站数据包发送到哪里。在这种情况下,路由器充当防火墙,阻止传入服务器的流量。

解决这个问题的基本方法是:

1) 开启 UPnP

这使您的应用程序能够指示路由器如何将入站流量转发回您的服务器。

2) 设置端口转发

如上通过手动配置路由器。

3) 让您的工作服务器成为客户端

路由器通过允许出站连接来启动连接来工作。它会记住返回地址,重写外部可见的 IP,并为外部流量提供一个未使用的端口以进行回话 (NAT)。这允许出站请求与外部建立通信并绕过防火墙。如果您的家庭 IP 是固定的,您可以在工作中设置一个客户端,尝试按计划呼叫家庭(直到您启动服务器并可以建立连接)。

4) 使用 P2P(中介服务器)

我不确定你会从哪里开始,但原则是这样的。它通常在单个 UDP 端口上工作。不位于 NAT 之后的服务器用于建立连接。客户端通过 UDP 数据包将其 IP 发送到服务器,路由器使用路由器返回地址重写 UDP 标头。服务器获取此数据并将其发送给其他对等方。现在每个人都知道对方的返回地址,他们可以直接向对方发送 TCP 流量,而服务器则让路。

有一些非常好的文章here 关于 NAT 的基础知识,用简单的术语进行了解释。还有一篇好文章 here 解释了 P2P 如何利用 NAT 绕过防火墙。

希望这能给你一些想法。

【讨论】:

  • 感谢您的帮助。如果你能告诉我为什么我仍然不能做 tcp puch holing 会很好...看看我对这个问题的更新。如果您能完成这项工作,我将不胜感激。
  • 我相信你正在尝试上面的 4)。这要求中间服务器不在 NAT 后面,否则返回地址会丢失,因为它在到达您的服务器之前被路由器重写。理想情况下,您需要传递到每台机器的路由器出站地址/端口将它们连接在一起。返回地址将是一些您无法预测的随机端口,并且只有 2 个路由器知道。
【解决方案2】:

有一篇关于 UDP 和 TCP 打洞技术的优秀文章。

http://www.brynosaurus.com/pub/net/p2pnat/

但是,对于这种打孔技术,您需要一个知名的集合服务器,我认为您不想设置它。

顺便说一句,您需要仔细检查公司关于在办公室拥有自己的服务器的政策。出于安全考虑,我认为公司不允许员工在内部设置自己的服务器。

【讨论】:

  • 您的链接很有帮助。我相信我做了你在链接上提到的事情。我不明白为什么它不起作用。看看我的更新...
【解决方案3】:

TCP 打孔经常不起作用。最好的办法是坚持使用 UDP 打孔。如果您需要类似 TCP 的行为,您可以使用 RDP 或提供 TCP 行为但可以使用 UDP 作为其传输的类似协议。

另一种方法是通过服务器中继所有流量。每个主机都可以连接到服务器,服务器可以将流量从一个连接复制到另一个。

最好的解决方案是,如果您可以从路由器获得一些支持,例如端口转发或 UPnP。

【讨论】:

  • 我想避免中继,因为那样会消耗服务器上大量的 cpu 使用率。但我会更多地研究 UPnP。非常感谢!
  • 我对此表示怀疑。 '486 可以中继 100Mbps。
  • 中继会更有效率吗?数据传输会更快吗?
  • 这取决于很多因素,包括您是否必须在用户空间伪造 TCP。
  • 我已经设法进行 udp 打孔。我正在传输文件,这就是我想使用 tcp 协议的原因。无论如何,正如你所说,这似乎很难实现。我认为应该可以确保在使用 udp 协议时不会丢失数据?
【解决方案4】:

您可以编写自己的代理:

服务器: 在 1300 上监听来自 A 的连接,在 1301 上监听来自 B 的连接。保留两个连接的列表,当每个连接至少有一个时,创建一个代理对象。此时,您从 B 向您的连接发出信号,表明您有一个连接,这可能是一个信号字节或一个端口,甚至是要连接的地址。之后,当你从 A 获取数据时,将其发送给 B。当你从 B 获取数据时,将其发送给 A。

计算机 B: 程序维护到服务器上端口 1301 的连接。如果连接断开,请重新建立连接。当您收到一个信号(可能有地址和端口或者只是一个“我有一个连接”字节)时,创建一个到所需端口的连接并将这两个连接存储在一个代理对象中。当您从一个接收数据时,将其发送给另一个。由于您正在使用该连接,因此请在服务器上建立一个到端口 1301 的新连接以处理更多。

当然,您必须处理断开的连接,在 B 和服务器之间始终打开的挂起连接之间发送保持活动信号会有所帮助。

这是我很久以前写的一个sample class 来做代理。我没有时间清理它,但是如果您看到 TcpProxy 是接受连接的父类,则 Client 是接受的连接,而 RemoteEndPoint 是要连接的端点。它还将数据写入文件并执行一些您可以忽略的其他操作。

【讨论】:

    猜你喜欢
    • 2016-06-06
    • 2012-03-28
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-08
    • 2019-12-22
    相关资源
    最近更新 更多