使用c#“UDP打孔到防火墙”将端口X的流量从端口X转发到计算机B

时间:2011-08-29 01:03:02

标签: c# networking tcp portforwarding

我需要建立从家用计算机到办公室计算机的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)
        //...

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

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

enter image description here

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

我确信应该有办法建立连接,因为办公室里的某些人使用limewire或比特洪流。我认为我的问题可能与权限有关吗?我该如何解决这个问题?


修改

因此,通过研究,我发现我要做的是“UDP打孔到防火墙”。我实际上想通过tcp连接来做。我不知道tcp和upd puch holing之间的区别是什么....我的意思是让客户端能够找到一个梨而不必在路由器上进行配置。

更新

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

请注意,您可能需要参考此图表以了解我将要解释的内容: enter image description here

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

第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 debug应如下所示:

enter image description here

第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正在等待新连接。 enter image description here

第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.

enter image description here

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

PS:

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

enter image description here

4 个答案:

答案 0 :(得分:4)

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

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

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

1)打开UPnP

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

2)设置端口转发

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

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

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

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

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

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

希望这会给你一些想法。

答案 1 :(得分:3)

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

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

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

答案 2 :(得分:2)

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

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

但是,你需要一个众所周知的会合服务器来实现这种打孔技术,我认为你不想设置它。

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

答案 3 :(得分:2)

您可以编写自己的代理:

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

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

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

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

相关问题