TCP打孔(NAT Traversal)库还是什么?

时间:2010-03-14 19:39:23

标签: c# tcp nat

我想在C#中进行TCP打孔(NAT Traversal)。如果需要,可以使用集合服务器完成。我发现http://sharpstunt.codeplex.com/但无法使其发挥作用。理想情况下,我需要一些方法,我将一个端口号(int)作为参数,在NAT上调用此方法后可用(“Port Forwarded”)。如果该方法只返回一些后来在NAT上可用的端口号,那也没关系。有没有人用C#做过这个?你能给我一些sharpstunt或其他东西的例子吗?

6 个答案:

答案 0 :(得分:18)

在每种网络场景中,TCP打孔操作的方式与UDP打孔方式类似。例如,如果两个对等体A和B落后于不同的NAT,则发送到另一个对等体的每个对等体的第一个SYN数据包在其各自的NAT中打开与其公共地址相关联的漏洞。如果A到B的第一个SYN数据包到达B的NAT,那么在B的第一个SYN数据包到A的B到达NAT之前,B的NAT认为A的SYN数据包是未经请求的并且丢弃了它。但是,随后B的第一个SYN数据包可以成功通过A的NAT,因为A的NAT将B的公共地址识别为A发起的传出会话的目的地。

是的。 TCP打孔是可能的。我不明白为什么有人会这么想。

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

通常,TCP打孔(3.2.1)如下进行:

客户:A,B 服务器:S

•A使用其与S的连接向S请求连接 与B. •S用B的私人和公共地址回复A, 并同时将A的地址发送给B.

•A和B以异步方式进行外向连接 - 诱惑(发送SYN数据包)到彼此的公共和 私有地址,来自他们使用的同一个端口 注册S.同时,他们听 TCP本地TCP上的传入连接尝试 端口。

•A和B等待对其外部的SYN-ACK响应 发送SYN数据包或传入连接请求 (SYN包)。如果连接失败,则对等方可以重试 它达到最大超时时间。

•三次握手过程完成后, 对等方互相认证。如果认证 - 如果失败,同伴关闭该连接并等到 另一个连接已成功通过身份验证该 将使用首先成功通过身份验证的连接 传输TCP数据。

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

答案 1 :(得分:3)

这个问题已经很老了,但是对于任何寻找解决方案的人来说,你应该看看Open.NAT project它真的很容易使用,并且可以使用UPNP和PMP NAT!

假设您要将外部端口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 Traversal的博文:https://blogs.msdn.microsoft.com/ncl/2009/07/27/end-to-end-connectivity-with-nat-traversal/

答案 2 :(得分:2)

听起来你可能会混淆TCP和UDP。 TCP是一种面向连接的协议,防火墙和路由器很容易理解,并且需要一个启动器(客户端)和一个监听器(服务器)。如果客户端和服务器都位于防火墙或NAT之后,则无法在没有连接到某个代理服务器(不是防火墙)的情况下打孔。问题在于,代理将负责转发所有流量。

从您的问题来看,听起来您对UDP打孔更感兴趣,它利用UDP无状态的胖,而不是面向连接。因此,大多数状态跟踪防火墙将对UDP数据流做出“最佳猜测”,并假设离开给定端口的流量将在同一端口上收到回复,并自动将它们路由回来。如果使用一些非通道方式(例如简单地传递地址而不是数据的TCP服务器),两个对等体可以在相同的端口上相互传输数据,它们各自的防火墙/ NAT路由器将打开允许的漏洞交通。

至于如何做,这一切都取决于你将如何获得对等方的IP地址。完成后,只需在约定的端口上开始传输UDP数据包,然后等待回复。

答案 3 :(得分:2)

我们整合了一个名为IceLink的库,它使用ICE / STUN / TURN进行P2P流式传输,并进行完整的NAT遍历。基于STUN的打孔工作适用于大多数路由器之间建立直接连接,并且对于“坏”#34;路由器在那里,连接回落到基于TURN的中继。

答案 4 :(得分:1)

http://sipsorcery.codeplex.com有一个有效的昏迷服务器。

SipSorcery.core - > SipSorcery.Net - >击晕

答案 5 :(得分:0)

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

祝你好运。