35

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

4

5 回答 5

23

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

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

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

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

客户:A、B 服务器:S

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

• A 和 B 从它们用来向 S 注册的同一端口异步地向对方的公共和私有地址进行传出连接尝试(发送 SYN 数据包)。同时,它们在其上侦听 TCP 传入连接尝试。本地 TCP 端口。

• A 和B 等待对其输出的SYN 数据包或输入的连接请求(SYN 数据包)的SYN-ACK 响应。如果连接失败,对等方可以重试,直到最大超时期限。

• 三次握手过程完成后,对等方相互验证。如果身份验证失败,对等方关闭该连接并等待另一个连接成功验证。第一个成功验证的连接将用于传输 TCP 数据。

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

于 2011-06-04T19:52:25.210 回答
4

这个问题已经很老了,但是对于任何正在寻找解决方案的人来说,您应该看看Open.NAT 项目,它非常易于使用并且可以与 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/

于 2016-05-18T18:28:30.163 回答
2

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

于 2012-12-04T23:06:30.257 回答
1

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

SipSorcery.core -> SipSorcery.Net -> Stun

于 2010-04-26T11:00:46.150 回答
1

听起来您可能会混淆 TCP 和 UDP。TCP 是一种面向连接的协议,很容易被防火墙和路由器理解,并且需要一个启动器(客户端)和一个侦听器(服务器)。如果客户端和服务器都在防火墙或 NAT 之后,那么如果不让它们都连接到某个代理服务器(没有防火墙),您就无法打洞。这样做的问题是代理将负责中继他们的所有流量。

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

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

于 2010-07-08T18:09:42.373 回答