web-dev-qa-db-ja.com

TCPホールパンチ(NATトラバーサル)ライブラリまたは何か?

やりたいTCP C#での穴あけ(NATトラバーサル)。必要に応じて、ランデブーサーバーで実行できます。 http://sharpstunt.codeplex.com/ しかし、これを機能させることができません。理想的には、このメソッドの呼び出し後にNATで使用できる(「ポート転送」)パラメータとしてポート番号(int)を指定するいくつかのメソッドが必要です。また、メソッドが一部のポート番号を返し、NATで利用できる場合は問題ありません。C#でこれを行った人はいますか?シャープスタントなどの実用的な例を教えてもらえますか?

35
TobiHeidi

各ネットワークシナリオでは、TCPホールパンチングはUDPホールパンチングと同様に動作します。たとえば、2つのピアAとBが異なるNATの背後にある場合、各ピアの最初のSYNパケットが他のピアに送信されますピアは、それぞれのNATでそのパブリックアドレスに関連付けられた穴を開けます。Aへの最初のSYNパケットがBに到達した場合NAT BがAへの最初のSYNパケットがBのNATに到達する前に、BはNATは、AのSYNパケットを未承諾と見なして破棄します。ただし、その後、Bの最初のSYNパケットは、AのNATを通過できます。これは、AのNAT Aが開始した発信セッションの宛先としてのBのパブリックアドレス。

あ、はい。 TCP holepunchとすることは可能です。なぜだれもが他の方法で考える理由はわかりません。

また、このタイプの動作を手動で作成できませんか?必要な情報をすべて収集する手順が同じである限り、特定のプロトコルに依存する必要はありません。

一般に、TCP穴あけ(3.2.1))は次のように進行します。

クライアント:A、Bサーバー:S

•AはSとの接続を使用して、Bとの接続をSに要求します。•SはBのプライベートアドレスとパブリックアドレスでAに返信し、同時にAのアドレスをBに送信します。

•AとBは、Sに登録するために使用していたのと同じポートから、互いのパブリックアドレスとプライベートアドレスに非同期で発信接続を試みます(SYNパケットを送信します)。同時に、TCPローカルでの着信接続試行TCPポート。

•AとBは、発信SYNパケットに対するSYN-ACK応答、または着信接続要求(SYNパケット)を待ちます。接続が失敗した場合、ピアは最大タイムアウト期間まで再試行できます。

•3ウェイハンドシェイクプロセスが完了すると、ピアは相互に認証します。認証が失敗した場合、ピアはその接続を閉じ、別の接続が正常に認証されるまで待機します。最初に正常に認証された接続は、TCPデータを転送するために使用されます。

(私はこれが答えの多くではないことを知っていますが、コメントのための十分な余地がありませんでした)。

21
SilverX

質問はかなり古いですが、解決策を探している人は、 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 /

4
JPelletier

ICE/STUN/TURNを使用してP2Pストリーミングを実行する IceLink というライブラリを、フルNATトラバーサルで実行します。ほとんどのルーターでSTUNベースのホールパンチングが機能します。ピア間の直接接続を確立し、そこにある「不良」ルーターの場合、接続はTURNベースのリレーにフォールバックします。

2
Anton

TCPとUDPが混同されているようです。TCPは接続指向のプロトコルであり、ファイアウォールとルーターで簡単に理解でき、1つのイニシエーターが必要です。 (クライアント)と1つのリスナー(サーバー)です。クライアントとサーバーの両方がファイアウォールまたはNATの背後にある場合、両方を(ファイアウォールではない)プロキシサーバーに接続しないと、穴を開けることはできません。この問題は、プロキシはすべてのトラフィックの中継を担当します。

あなたの質問から、UDPはステートレスであり、接続指向ではないという脂肪を悪用するUDPホールパンチングに興味があるようです。したがって、ほとんどの状態追跡ファイアウォールは、UDPデータフローについて「最も適切な推測」を行い、特定のポートに送信されるトラフィックが同じポートで応答を受信し、それらを自動的にルーティングすると想定します。いくつかのアウトオブチャネル手段(TCPサーバーがアドレスではなくデータを渡す)など)を使用する場合、両方のピアが同じポートでお互いにデータを送信できます。ファイアウォール/ NATルーターは、トラフィックを許可する穴を開けます。

その方法は、ピアのIPアドレスを相互に取得する方法によって異なります。それができたら、合意されたポートでUDPパケットの送信を開始し、応答を待ちます。

2
Tyr

http://sipsorcery.codeplex.com は、動作中のスタンサーバーを持っています。

SipSorcery.core-> SipSorcery.Net->スタン

1
jgauffin