Uwierzytelnianie w grze wieloosobowej za pośrednictwem gniazd
11
Wdrażam niestandardowy protokół binarny dla nowej gry wieloosobowej, nad którą pracuję. To turowa gra strategiczna, więc czas nie ma znaczenia. Obecnie mam ukończoną podstawową synchronizację danych w systemie i zastanawiałem się, w jaki sposób logowanie / wylogowywanie i szyfrowanie użytkowników jest zwykle wykonywane w grach MMORPG lub podobnych.
Czy możesz polecić schemat bezpiecznej / tajnej transmisji hasła podczas logowania? (Wymiana kluczy Diffie-Hellman?)
Jak zaimplementować silne szyfrowanie pakietów danych? (AES 128-bit? .. czy jakikolwiek schemat, który ten post nazywa „szyfrowaniem silniejszym, niż prawdopodobne”)
Czy istnieją schematy formatu datagramów, które pomagają zahartować serwer gry w celu powtórzenia ataków, nieprawidłowych pakietów danych i tym podobnych?
SRP - Bezpieczne hasło zdalne - oparte na Diffie-Hellman. Chodzi o to, że możesz wykonać wzajemną kontrolę hasła bez faktycznego przesyłania hasła lub jakichkolwiek informacji, które można by wykorzystać do jego uzyskania. Mimo, że jest bezpieczny przez sieć, nadal powinieneś mieszać i solić hasła, ponieważ serwer nigdy nie może przechowywać ich w postaci zwykłego tekstu .
Zaletą SRP jest to, że po jego zakończeniu daje również wynegocjowany wspólnie klucz szyfrowania, którego atakujący nie byłby w stanie wydedukować, biorąc pod uwagę przesłane dane. Oznacza to, że możesz swobodnie korzystać z algorytmu szyfrowania symetrycznego (takiego jak AES) po uwierzytelnieniu użytkownika.
Zakładając, że używasz UDP z własną niezawodną / uporządkowaną (zorientowaną na połączenie) implementacją: zaszyfruj całą playlistę UDP - w tym swój „numer sekwencji pakietu”. Jeśli twój system jest poprawnie zaprojektowany, automatycznie odrzuci odtwarzane wiadomości, a intruz nie będzie mógł zmienić numeru sekwencji pakietu, ponieważ jest on zaszyfrowany (w ten sposób powtórka jest możliwa - ale zostanie automatycznie zignorowana).
Myśli
Czy twoje uwierzytelnianie powinno być bezpieczne? Absolutnie. Nie kwestionuj bezpieczeństwa, jeśli chodzi o hasło. Dlatego zdecydowanie powinieneś rozważyć pierwszą kulę w mojej odpowiedzi.
Czy twoje dane powinny być bezpieczne? Tylko jeśli jest to zakup / mikro-transakcja w grze - i dlaczego nie skorzystać z czegoś wypróbowanego i prawdziwego, takiego jak HTTPS. Szyfrowanie ruchu w grze prawdopodobnie nie jest realnym rozwiązaniem z następujących powodów:
To całkowita paranoja.
Zwiększy czas pracy procesora na twoim serwerze, chyba że możesz kupić (drogie) sprzętowe moduły szyfrujące.
Nie ma znaczenia, ile bezpieczeństwa zapewniasz swoim danym przez sieć - ktoś może przejąć kontrolę nad procesem klienta i przechwycić wiadomości na chwilę przed ich zaszyfrowaniem i wysłaniem. Jest to nie tylko możliwość, ale nieskończenie bardziej możliwa, ponieważ znacznie łatwiej jest wstrzykiwać kod w porównaniu do przechwytywania pakietów. Jeśli robisz to w celu zapobiegania oszustwom, całkowicie i całkowicie marnujesz swój czas.
Jeśli chodzi o bezpieczeństwo hasła, niestety nic nie można zrobić z porwanym systemem, klient stał się wrogi. Klucze sprzętowe WoW Blizzards są zaprojektowane, aby sobie z tym poradzić - ale nie jestem pewien, jak bezpieczne jest to rozwiązanie (szczególnie jeśli pozostawisz je podłączone).
Proszę, jeśli szyfrowanie dla zapobiegania ściągawki z niego zrezygnować. Niedługo wyjdziesz - dałem ci informacje na wypadek, gdybyś nie był. Pamiętaj, że możesz selektywnie szyfrować pakiety za pomocą pierwszego bajtu w pakiecie i wskazać, czy reszta jest zaszyfrowana: chociaż po raz kolejny trzymałbym się HTTPS, jeśli musisz robić rzeczy takie jak transakcje kartą kredytową: są one bardzo rzadkie i HTTPS został zaprojektowany przez ekspertów - inaczej niż coś, co zaprojektowałeś ty lub ja.
Wszystko to mówi, że Blizzard faktycznie szyfruje swój ruch WoW. Głównym powodem tego zerwania jest to, że ktoś, kto jest prawdopodobnie kompletnym amatorem, zdecydował, że spróbuje swoich sił w domowym algorytmie szyfrującym; bardzo dobrze to przeszło . Nawet jeśli używasz standardowych algorytmów branżowych, istnieje duża szansa, że ktoś dokona inżynierii wstecznej Twojego kodu i zasymuluje go - po wprowadzeniu hasła przez klienta nie będzie już wiadomo, że podłączony jest nieobsługiwany system.
+1 za powiedzenie, że szyfrowanie pakietów danych w celu zapobiegania oszustwom jest bezużyteczne. OP: zweryfikuj wszystko, co otrzymujesz od klienta, uruchom kontrole poczytalności, sprawdź dwukrotnie, czy żądana akcja jest możliwa, sprawdź zasięg broni, prędkość ruchu itp., Ale nie marnuj czasu na zabezpieczenie swojego klienta, ponieważ zostanie zhakowany, jeśli twoja gra jest tego warta. Niektóre firmy MMO szyfrują i zaciemniają swoich klientów / protokoły, ale nie ma to na celu zapobiegania oszustwom, ale utrudnianie np. Twórcom botów osiągania dobrych wyników, a nawet robią to oddane zespoły ekspertów.
Gilead
1
Drobna sprzeczka na temat trzeciej odpowiedzi: samo szyfrowanie pakietów może nie wystarczyć, aby zapobiec manipulowaniu, ponieważ wiele schematów szyfrowania jest co najmniej w pewnym stopniu podatnych na modyfikację . Aby chronić integralność wiadomości, potrzebujesz trybu MAC lub uwierzytelnionego trybu szyfrowania .
Ilmari Karonen
+1 Dziękujemy za bardzo kompletną odpowiedź. Patrząc teraz na wdrożenie SRP. Jakie są zalecenia dotyczące funkcji skrótu używanej do haseł? MD5? Jaki byłby protokół OTR (Off the Record) dla takiego przypadku użycia? czy działałoby to dobrze dla auth / crypto zamiast SRP? Czy w przypadku korzystania z SRP musiałbym użyć jednego z następujących trybów „szyfrowania uwierzytelnionego”? (OCB 2.0, Key Wrap, CCM, EAX, Encrypt-then-MAC i GCM)
Robinicks
1
@Jenko korzysta z rodziny algorytmów SHA (prawdopodobnie SHA1) - w dzisiejszych czasach należy unikać MD5. OTR nie jest naprawdę coś należy szukać w - to nie jest przeznaczony do bezpiecznego / zaciemniać (w rzeczywistości jego zaprojektowany tak, że ktoś może bardziej łatwo podrobić pakietów) to również przeznaczone do komunikacji błyskawicznej, a nie komunikacji urządzenia. Żaden z tych trybów nie jest potrzebny, wystarczy użyć SRP: gdy masz już wynegocjowany klucz symetryczny, po prostu możliwość zaszyfrowania czegoś jest wystarczającą gwarancją, że rozmawiasz z właściwą stroną trzecią. Ponownie przeczytaj też moje ostatnie dwa akapity.
Jonathan Dickinson
1
Właściwie mam jeszcze lepszą sugestię: użyj istniejącego DTLS zamiast implementacji UDP i nie próbuj tworzyć własnych. Zaoszczędzi ci to czasu, a jest wiele drobnych, ale krytycznych szczegółów, które można łatwo pomylić, próbując zaprojektować własną warstwę szyfrowania datagramów.
Ilmari Karonen
2
Myślę, że mój ostatni komentarz do doskonałej odpowiedzi Jonathana warto rozszerzyć na odpowiedź własną:
Jeśli nie masz dużego doświadczenia w kryptografii, nie powinieneś próbować projektować własnej warstwy szyfrowania, jeśli możesz tego uniknąć. Jeśli zrobić dużo krypto doświadczenia, powinieneś wiedzieć lepiej niż zaprojektować własną warstwę szyfrowania, jeśli można tego uniknąć.
Zamiast tego spróbuj znaleźć istniejącą, znormalizowaną i dobrze przetestowaną bibliotekę kryptograficzną, która robi to, czego potrzebujesz. W twoim przypadku polecam GnuTLS , który według Wikipedii zapewnia zarówno uwierzytelnianie TLS-SRP ( RFC 5054 ), jak i bezpieczną komunikację UDP z DTLS ( RFC 6347 ). Pierwszy z nich zajmuje się logowaniem, a drugi chroni w ten sposób bezpieczny kanał utworzony zarówno przed podsłuchiwaniem, jak i aktywnymi atakami, a nawet może chronić cię przed atakami powtórkowymi .
Używam TCP. Jest to zupełnie inna gra dla konkretnego klienta. Podobnie jak hazard / zakłady, wszystkie informacje, które można wykorzystać do przejęcia kontroli nad procesem, zwiększają szanse na niepotrzebne straty kasyna. Musimy zapewnić bezpieczeństwo danych, ponieważ w tym przypadku informacja to pieniądz.
Robinicks,
OK, jeśli używasz TCP, to jest jeszcze łatwiejsze: możesz użyć normalnego TLS 1.2 zamiast DTLS, co daje więcej opcji do wyboru. Nadal jednak polecam bibliotekę GnuTLS.
Ilmari Karonen
Zrobię trochę badań i zobaczę, czy mogę odwoływać się do kodu źródłowego TLS zarówno po stronie klienta, jak i serwera, i oprzeć mój protokół na tym, co robi. Czy to byłoby wystarczająco silne? Zasadniczo jest to po prostu szyfrowanie pakietów za pomocą jakiegoś szyfru / trybu, prawda?
Robinicks,
Nie, protokół TLS oferuje znacznie więcej. Dlatego chcesz użyć standardowej biblioteki, która ją implementuje, zamiast tworzyć własną.
Myślę, że mój ostatni komentarz do doskonałej odpowiedzi Jonathana warto rozszerzyć na odpowiedź własną:
Jeśli nie masz dużego doświadczenia w kryptografii, nie powinieneś próbować projektować własnej warstwy szyfrowania, jeśli możesz tego uniknąć. Jeśli zrobić dużo krypto doświadczenia, powinieneś wiedzieć lepiej niż zaprojektować własną warstwę szyfrowania, jeśli można tego uniknąć.
Zamiast tego spróbuj znaleźć istniejącą, znormalizowaną i dobrze przetestowaną bibliotekę kryptograficzną, która robi to, czego potrzebujesz. W twoim przypadku polecam GnuTLS , który według Wikipedii zapewnia zarówno uwierzytelnianie TLS-SRP ( RFC 5054 ), jak i bezpieczną komunikację UDP z DTLS ( RFC 6347 ). Pierwszy z nich zajmuje się logowaniem, a drugi chroni w ten sposób bezpieczny kanał utworzony zarówno przed podsłuchiwaniem, jak i aktywnymi atakami, a nawet może chronić cię przed atakami powtórkowymi .
źródło