Skocz do zawartości
gnysek

39dll - UDP Hole Punching

Rekomendowane odpowiedzi

Ostatnio natknąłem się w sieci na ciekawe zagadnienie, mianowicie UDP hole punching. Nie wiem jaki jest polski odpowiednik, jedyny na jakie się natknąłem (wiercenie dziur) to dosłowne tłumaczenie, więc pozostanę przy angielskiej wersji.

 

UDP jest protokołem który wymaga mniej danych do przesłania pakietu, więc oszczędza łącze, ale z drugiej strony jeśli pakiet nie dotrze, to przepada jak kamień w wodę i tyle. Nadaje się jednak do przesyłania pozycji itp. - czyli rzeczy które w razie czego skoryguje następny pakiet, gdyby jakiś po drodze przepadł.

 

Więc na czym owo UDP Hole Punching polega? Otóż jak wiecie (np. kto testował Alienów Borka), połączenia przychodzące UDP są przez router/firewall blokowane, natomiast wychodzące nie.

 

Cała sztuczka polega na wykorzystaniu tego faktu - otóż gdy wyślemy jakiś pakiet UDP, to router dostaje o tym informację i czeka na pakiet zwrotny z serwera potwierdzający dostarczenie - i w tym momencie otwieramy nasz router na pakiet UDP, który serwer może zwrócić. To z kolei otwiera kolejną możliwosć.

 

Mamy Serwer S, oraz klientów - A i B. Znajdują się za sieciami NAT N1 i N2 - które blokują przychodzące UDP.

Klienci podłączają się do serwera S, każdy z nich dostaje jakiś wyznaczony port UDP który nie jest akurat lokalnie wykorzystywany. I teraz najfajniejsza zabawa: serwer A wysyła pakiet, np. po porcie 6000 z portu 6000 na port 6001 IP klienta B - zgodnie z zasadą, router czeka na zwrot. Firewall serwera B odrzuca jednak ten pakiet, a że to UDP, pakiet przepada i żadne info nie wraca. Klient B również wysyła pakiet UDP po porcie 6000 z portu 6001 na port 6000 do klienta A - teoretycznie router powinien je odrzucić - ale - w związku z tym, że posłał przed chwilą pakiet UDP, czeka na odpowiedź - więc pakiet z komputera B może sobie spokojnie przejść. Router zakańcza oczekiwanie na ten pakiet, ale teraz to B ma w routerze/firewallu dziurę która czeka na odpowiedź. Klient A może więc znów wysłać pakiet - i w ten sposób dwóch klientów komunikuje się bezpośrednio ze sobą, bez użycia serwera.

 

Mam kilka zagadnień które wymagają rozwiązania:

- co, gdy pakiet przepadnie po drodze i nie dotrze do dziury? Jak długo router pozostanie otwarty (ofc. po stronie klienta mozna dorobić numerowanie pakietów dla pełnej kontroli)

- jeżeli w grze online gra 200 graczy, to wszyscy między sobą rozsyłają dane po UDP, każdy na innym porcie, czy tylko niektórzy (bo na pewno wszystkie dane nie lecą z serwera, tylko korzystają z faktu UDP Hole Punching)

 

Podobnoż Hamachi również korzysta własnie z tego faktu.

 

Czy ktoś z was bawił się w hole punhcing, lub ma jakąs większą wiedzę na ten temat?

 

Edit: macie to też wytłumaczone tutaj: http://www.heise-online.pl/security/featur...lli-778097.html - dolna częśc strony.

Udostępnij tego posta


Odnośnik do posta
Udostępnij na innych stronach

O kurde. Ciekawe to. To by znacznie poprawiło jakość grania graczom bez zew. adresu IP, jeśli mówić o grach zrobionych na 39dll.

 

EDIT: Poczytalem o tym, fajne to. Będę musiał to sprawdzić.

Gnysku, nie każdy musi korzystać z innego portu. Przecież dane są wysyłane na dany port ORAZ IP! A żeby ich router nie losował portów to możesz od gracza wymagać otwarcia specyficznych portów na routerze, w dzisiejszych czasach to już i tak standard.

Udostępnij tego posta


Odnośnik do posta
Udostępnij na innych stronach

Własnie mnie ten przykład ze skype zastanawia - dlaczego oni obaj po tym samym porcie nie jadą... przecież to nie ma znaczenia, bo router działa na zasadzie:

 

MOJE_IP:PORT -> INNE_IP:PORT -> MOJE_IP:PORT

 

Zatem musi się zgadzać IP i port z którego przychodzi pakiet i na które ma trafić pakiet, bo tylko takie dane router uzna za dobre (inaczej dziurę mógłby wykorzystać haker), więc chyba nie stoi na przeszkodzie aby były te same.

Problem się robi gdy router zaczyna przekształcać porty, np dodając coś do nich. Pół biedy, jak dodaje ciągle tę samą liczbę, ale jak robi randoma, no to pozostaje TCP, nie mniej implementacja nawet stałego dodawania to już trochę dodatkowego kodu (może nie trudne, ale żmudne)

 

Nie mniej jeśli się temu przyjrzysz czekam na informację.

Udostępnij tego posta


Odnośnik do posta
Udostępnij na innych stronach

to to o czym Ci na gg powiedziałem tak? otóż wystarczyło się zapytać jeszcze raz... każdy NAT ma indywidualny czas do zakończenia czekania na pakiet (może to być 30/50/120 sekund [nie ma standardu] ale średnia to 20 sekund) dlatego można wysyłać ping co 5 sekund (który może przepaść) lub zrobić funkcje która będzie wykrywała czy dziura już jest zamknięta i otworzy ją ponownie... Drugie... 200 graczy... Tak, każdy z każdym i do każdego pod warunkiem, że są na widoku (np GM), oszczędzając wtedy łącze... To jest wykorzystywane w grach multi typu l4d2, tf2 itd, serwer główny działa głównie jako informator o ip i portach. Kiedy chcemy grać na przykład za 1 NAT'em a nie dwoma, dobrze jest wysyłać ip wewnętrzne razem z ip zewnętrznym i próbować robić dziury na obu IP. Rozwiązuje to wiele problemów. Może jak będę miał czas pomiędzy kodzeniem dla Ciebie serwerka Almory (na który nadal czekam na specyfikacje pakietów) a moim programem VoIP (być może napiszę taką bibliotekę dla GM by można było się komunikować podczas gier) to napiszę przykład :) Open Source C++/Delphi jak kto będzie chciał.

 

Co do TCP... w TCP także istnieje Hole Punching, trudniejszy do zaimplementowania ale działa :)

 

Miej na względzie, że oprócz NAT trzeba także przejść obok firewalla od antywirusa lub zapory sieciowej (ale to może już wyłączyć użytkownik).

 

na UDP H-P trafiłem kiedy przesyłanie dużej ilości pakietów voice przez serwer spaliło na panewce ;p

Udostępnij tego posta


Odnośnik do posta
Udostępnij na innych stronach

Mineło 3 latka i temat do mnie wrócił jak strzała. Chcę zaimplementować multiplayer na zasadzie kombinacji p2p ale w taki sposób, że jest tylko 1 host przez ktorego wędrują dane do reszty graczy. Tyle, że ten 1 host to będzie jeden z graczy. Dawniej kiedy nikomu z nas na jakości aż tak bardzo nie zależało, po prostu olewało się problem publicznego IP i mówiło się otwarcie "Ściągnijcie sobie hamachi". Dziś to nie przejdzie :D.

 

Aby każdy mógł sobie zahostować grę (bez potrzeby posiadania publicznego IP) należy przeprowadzić zarówno UDP jak i TCP hole punching lub jak kto woli NAT punch-through.

Moje pytanie brzmi, czy obecny Networking w GM:S jest w stanie to zrobić. Nie wiem czy ktoś próbował się bawić, tym networkingiem, ja próbowałem i jest problem. Problem polega na tym, że GM nie daje nam kontroli co do tego na jakim porcie otwieramy swoje sockety. Tzn. daje nam możliwość kontrolowania tej sprawy w przypadku socketów nasłuchujących, ale nie w przypadku portów wysyłających (tak, to śmiesznie zrobione, ale w GM:S żeby móc funkcjonować na protokole UDP należy otworzyć 2 oddzielne sockety, 1 jako server-socket i 1 jako socket do wysyłania, nawet na kliencie gry).

 

Cały koncept obczytałem tutaj: http://www.brynosaurus.com/pub/net/p2pnat/

Jednak są momenty gdzie brak znajomości "technicznego angielskiego" trochę dokucza.

 

Pomińmy taką bzdurę jak omijanie routera, ponieważ dzisiaj naprawdę port forwarding to już nie jest czarna magia i tutaj można konsumenta zmusić do tego, żeby odblokował sobie porty na domowym routerze. Problem się pojawia gdy to ISP odgrywa rolę NATu, wtedy trzeba przebić dziurę.

Mam takie jeszcze pytanie małe do kogoś kto sie orientuje w tym dokładnie jak działają NATy. Jeśli mamy podobną architekturę jak ta którą wyjaśnił Gnynsek, czyli mamy komputery A i B, gdzie każdy jest zasłonięty przez swój NAT, niech będzie to NATa i NATb. Czy NATy same rozkminiają odpowiedni routing w przypadku hole punchingu?

 

PRZYKŁAD:

Komputer A wysyła pakiet z protu 6000 do serwera S. Ponieważ po drodze NATa mógł zmienic port na np. 6500 bo taki ma wolny to serwer S zapamietuje ze wiadomosc przyszła z publicznego adresu IP NATa + port 6500. To są publiczne dane, które później S wyśle dla komputera B. Ta sama sytuacja tylko w drugą stronę zrobi sie gdy komp B wyśle pakiet do serwera S. Ostatecznie chodzi mi o to, że komputer B wyśle wiadomość nie na port 6000 bo ten został zakryty przez NATa. Komp B wyśle pakiet na IP NATa : 6500 (czyli na publiczne dane). Teraz czy NATa zrozumie, że jest to odpowiedź, która jest adresowana do A i sam przekieruje wiadomosc odpowiednio?

 

Ogólnie ponieważ UDP w GM:S wymaga otwarcia 2 socketów (do wysyłania i do odbierania) i nie ma możliwości kontroli na jakim porcie otwiera się ten wysyłający socket, to wydaje mi się, iż zrobienie H-P jest po prostu nie możliwe, ponieważ NAT będzie przekierowywał odpowiedź na port, z którego wiadomość wyszła na początku, a ponieważ to nie będzie ten sam port, na którym otworzyliśmy socket nasłuchujący to wiadomość pójdzie sie walić. :/

 

Czy komuś udało się w pełni zaimplementować taki hole punching? Bonus points jeśli na GMie.

Udostępnij tego posta


Odnośnik do posta
Udostępnij na innych stronach

Sprawa jest skomplikowana, w zależności od rodzaju NATu i ogólnych założeń. Ogólnie fajnie jest kiedy wysyłając pakiet UDP do serwera otwieramy port UDP i jest dostępny na połączenia z każdego ip. Sprawa się komplikuje kiedy router sprawdza czy otrzymał odpowiedź UDP z tego samego adresu IP do którego wysłał pakiet. Wtedy można zastosować technikę "zgadywania" portów. Wiadomo, że podczas hole punching musisz wysłać pakiety UDP "każdy do każdego", jednak te pakiety giną i nie jesteś wtedy wstanie stwierdzić, które porty były użyte... Co do portów i tego co pytałeś:

 

http://samy.pl/pwnat/ to Ci się może przydać

 

Klient -> NAT -> SERWER -> NAT -> Klient to prosta sprawa nie wymagająca zbyt brain stormingu, sprawy się komplikują kiedy mamy klient->nat->nat -> klient 2 -> nat -> nat -> klient... W grę wchodzi zgadywanie otwartych portów i inne rzeczy, w zależności od konfiguracji NAT. Niestety nie da się stworzyć idealnej dziury p2p udp. Ale można wykorzystać hole punching do wysyłania danych po UDP z serwera do klienta (gdzie normalnie nie jest to możliwe gdy klient jest za NAT).

Udostępnij tego posta


Odnośnik do posta
Udostępnij na innych stronach

Ale jednak dużo profesjonalnych gier (np Torchlight 2) śmiga tylko w trybie p2p więc jakoś to muszą robić.

Udostępnij tego posta


Odnośnik do posta
Udostępnij na innych stronach

Taki

które jest bardo dynamiczną strzelanką także śmiga po p2p. Widać to po pingach że nie da się sprawdzić swojego pingu tylko pingi innych i dla jednych osób możesz być laggerem a dla drugich nie. I to zależy zwykle od odległości jaka graczy dzieli. Np z każdym polakiem mam pinga wysokości 20-40ms a z turasami po 300ms.

Udostępnij tego posta


Odnośnik do posta
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się tutaj.

Zaloguj się tutaj

  • Przeglądający   0 użytkowników

    Brak zarejestrowanych użytkowników, przeglądających tę stronę.

×