2010-03-14 16 views
32

Chcę wykonać TCP Hole Punching (NAT Traversal) w języku C#. W razie potrzeby można to zrobić za pomocą serwera rendezvous. Znalazłem http://sharpstunt.codeplex.com/, ale nie mogę tego uruchomić. Idealnie potrzebuję jakiejś metody, którą daję numer portu (int) jako parametr, który po wywołaniu tej metody jest dostępny ("Port Forwarded") w NAT. Byłoby dobrze, gdyby metoda właśnie zwróciła pewien numer portu, który jest wtedy dostępny w NAT. Czy ktoś zrobił to w języku C#? Czy możesz podać mi działające przykłady ostrej akcji lub czegoś innego?TCP Hole Punch (NAT Traversal) Biblioteka czy coś?

+0

Hmm ... dlaczego jest to szczególny przypadek potrzebne? jeśli chodzi tylko o połączenie, zainstaluj dowolny serwer proxy i skonfiguruj go w WebClient. powinien również rozwiązać problem. – cRichter

+1

Serwery proxy działają wolno i nie są bezpieczne. – Matth3w

Odpowiedz

15

W każdym scenariuszu sieciowym dziurkowanie TCP działa w podobny sposób, jak w przypadku dziurkowania UDP. Na przykład, jeśli dwa równorzędne A i B znajdują się za różnymi adresami NAT, pierwszy pakiet SYN każdego z uczestników wysłany do drugiego uczestnika otwiera otwór związany z jego publicznym adresem w jego odpowiednim NAT. Jeśli pierwszy pakiet SYN do B dojdzie do NAT B, zanim pierwszy pakiet SYN B do A osiągnie NAT, NAT B oznacza pakiet SYN A niezamówiony i upuszcza go. Jednak pierwszy pakiet SYN B może pomyślnie przejść przez NAT NAT, ponieważ A's NAT rozpoznaje publiczny adres B jako cel sesji wychodzącej, którą zainicjował A.

Tak, tak. Możliwe jest holokształtowanie TCP. Nie rozumiem, dlaczego ktokolwiek mógłby myśleć inaczej.

Nie możesz również utworzyć tego typu bahaviour ręcznie? Nie musi zależeć od żadnego konkretnego protokołu, o ile kroki są takie same, aby zebrać wszystkie wymagane informacje.

Ogólnie, przebijanie otworu TCP (3.2.1) prowadzi się w następujący sposób:

klientów A, B serwera S

• A wykorzystuje związek z S S zawiera dla połączenia z B. • S odpowiedzi na A z B prywatnych i publicznych wystąpieniach, i jednocześnie wysyła adresuje do B.

• A i B asynchronicznie dokonać połączenia wychodzące AT- kusi (wysyłanie pakietów SYN) do siebie pomieszczeniach i prywatnej adresy z tego samego portu, którego użyły do ​​rejestracji przy użyciu numeru . Jednocześnie nasłuchują połączeń przychodzących TCP na swoich lokalnych portach TCP .

• A i B czekają na odpowiedź SYN-ACK na ich wychodzące pakiety SYN lub przychodzące żądanie połączenia (pakiet SYN). Jeśli połączenie nie powiedzie się, uczestnik może ponowić próbę od aż do maksymalnego limitu czasu.

• Po zakończeniu trzydniowego procesu uzgadniania, , użytkownicy uwierzytelniają się nawzajem. Jeśli uwierzytelnianie zakończy się niepowodzeniem, węzły sieciowe zamykają to połączenie i czekają, aż inne połączenie zostanie pomyślnie uwierzytelnione. Najpierw pomyślnie uwierzytelnione połączenie zostanie użyte do transferu danych TCP.

(Wiem, że to nie jest duża odpowiedź, ale nie było wystarczająco dużo miejsca na komentarz).

+0

Nie zadziała w przypadku Enterprise NATs (symetryczny NAT). Dlaczego A i B wysyłają na prywatny adres? Nie można ich przekierować przez Internet. To, co opisujesz, to STUNT – tobias

+1

Po prostu opisuję proces dziurkowania. STUNT to rzeczywisty zestaw narzędzi wspomagających proces dziurkowania. Głównym punktem mojej odpowiedzi było pokazanie, że dziurkowanie TCP jest możliwe, ponieważ ktoś o tym wspomniał. Mam świadomość, że istnieją scenariusze, w których nie będzie działać, ale nie o to chodziło. (Jeśli chodzi o powód, dla którego podano adres prywatny, nie wiem, skopiowałem większość danych z innych źródeł). – SilverX

+1

Wikipedia dla STUN w "Ograniczeniach": Ponieważ adres IP serwera STUN różni się od adresu punktu końcowego, w symetrycznym przypadku NAT, mapowanie NAT będzie inne dla serwera STUN niż dla punktu końcowego. TURN oferuje lepsze wyniki z symetrycznym NAT. – SilverX

1

Nie znam się na twoim temacie, ale zdaję sobie sprawę, że mam open source P2PVPN, który używa biblioteki lib do robienia NAT. Możesz to sprawdzić tutaj (www.SocialVPN.org).

Powodzenia.

1

ma działający serwer oszałamiający.

SipSorcery.core -> SipSorcery.Net -> Paralizator

+0

Chciałbym mieć STUNT nie STUN, ale dzięki temu może być punktem wyjścia – TobiHeidi

+0

Myślę, że ma oba. Stunt jest po prostu ogłuszany przez TCP, prawda? – jgauffin

+0

Stunt jest ogłuszony, ale z TCP zamiast UDP. Nie możesz po prostu zastąpić UDP przez TCP i działa jak magia. Niestety: SipSorcery.core -> SipSorcery.Net -> Ogłuszenie NIE zapewnia STUNT ... – TobiHeidi

3

Brzmi to może być coraz TCP i UDP pomieszane. TCP jest protokołem zorientowanym na połączenie, łatwym do zrozumienia przez zapory ogniowe i routery, i wymaga jednego inicjatora (klienta) i jednego słuchacza (serwera). Jeśli zarówno klient, jak i serwer znajdują się za zaporami ogniowymi lub NAT, nie można przebić dziury bez połączenia się z jakimś serwerem proxy (który nie jest zaporą ogniową). Problem polega na tym, że wtedy proxy będzie odpowiedzialny za przekazywanie całego ich ruchu.

Z twojego pytania wynika, że ​​bardziej interesuje Cię dziurkowanie UDP, które wykorzystuje tłuszcz, który UDP jest bezpaństwowy, a nie zorientowane na połączenie. Dlatego większość zapór ogniowych śledzących stan "najpewniej zgadnie" o przepływie danych UDP i zakłada, że ​​ruch wychodzący z danego portu będzie otrzymywać odpowiedzi na tym samym porcie i automatycznie je odsyła. Jeśli za pomocą niektórych środków poza kanałem (takich jak serwer TCP, który po prostu przekazuje adresy, a nie dane), oba urządzenia równorzędne mogą przesyłać dane do siebie nawzajem na tych samych portach, a ich odpowiednie ściany ogniowe/routery NAT będą otwierać otwory umożliwiające ruch w.

Co do tego, jak to zrobić, wszystko zależy od tego, w jaki sposób uzyska się adres IP rówieśników. Kiedy już to zrobisz, po prostu zacznij przesyłać pakiety UDP na uzgodniony port i czekaj na odpowiedź.

+0

Potrafię zrobić dziurkowanie UDP, które jest oznaczone jako STUN, całkiem proste. ALE możesz zrobić dziurkowanie TCP, jest to po prostu bardziej skomplikowane i nazywa się STUNT (ostatnie T jest dla TCP). http://sharpstunt.codeplex.com/ roszczenia są w stanie to zrobić, ale nie mogę go uruchomić. Są też niektóre biblioteki JAVA, które to robią ... – TobiHeidi

+0

+1 Jeśli zarówno klient, jak i serwer znajdują się za zaporami ogniowymi lub NAT, nie można przebić dziury bez połączenia z jakimś serwerem proxy. – Valmond

+0

Należy pamiętać, że STUN nie pracować ze wszystkimi rodzajami NAT. ICE definiuje TURN jako rezerwowy. – tobias

2

Połączyliśmy bibliotekę o nazwie IceLink, która przesyła strumieniowo P2P za pomocą ICE/STUN/TURN z pełną translacją NAT. W przypadku większości routerów dziurkowanie w systemie STUN działa w przypadku większości routerów w celu nawiązania bezpośredniego połączenia między urządzeniami równorzędnymi, a w przypadku "złych" routerów połączenie powraca do przekaźnika opartego na protokole TURN.

+0

Wygląda na to, że jest to komercyjna biblioteka (po prostu mówiąca) – Valmond

2

Pytanie jest dość stare, ale dla każdego, kto szuka rozwiązania, powinieneś rzucić okiem na Open.NAT project, który jest naprawdę łatwy w użyciu i działa zarówno z NAT UPNP jak i PMP!

Powiedzmy, że chcesz przekierować portu zewnętrznego 1700 do lokalnego portu 1600, wszystko co musisz zrobić, to:

var discoverer = new NatDiscoverer(); 
var device = await discoverer.DiscoverDeviceAsync(); 
await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 1600, 1700, "The mapping name")); 

Można również wymienić wszystkie istniejące mapowania, aby można było zweryfikować, czy port nie jest już użyte.

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()); 

Istnieje również blogu o translacji NAT na MSDN: https://blogs.msdn.microsoft.com/ncl/2009/07/27/end-to-end-connectivity-with-nat-traversal/

+0

pracuję z przerwami dla mnie ... – beppe9000

+0

Tak, to trochę trudne, aby działało idealnie i przy użyciu jakiegoś sprzętu sieciowego może w ogóle nie działać. – JPelletier

Powiązane problemy