Taktyki bezpieczeństwa i zapobieganie oszustwom

*Ta zawartość została przetłumaczona przy użyciu narzędzi AI (w wersji beta) i może zawierać błędy. Aby wyświetlić tę stronę w języku angielskim, kliknij tutaj.

Roblox używa dystrybucyjnego systemu fizyki, w którym klienci mają opiekę nad fizyczną simulacją obiektów w ich kontrolach, zwykle postać gracza i niezakorzenione obiekty blisko tej postaci. Ponadto poprzez użycie oprogramowania stron trzecich, eksploatatorzy mogą wykonawać dowolny kod Lua na kliencie, aby manipulować ich modelem danych i dekom

Zbiorowo, to oznacza, że doświadczony eksploiter może potencjalnie wykonują kod do oszustw w gra, w tym:

  • Teleportowanie ich własnego postaci wokół miejsce.
  • Wystrzeliwanie niezabezpieczonych RemoteEvents lub wezwywanie RemoteFunctions, takich jak nagradzanie siebie przedmiotami bez ich zarabiania.
  • Dostosowywanie Class.Humanoid.WalkSpeed|WalkSpeed ich postaci, aby poruszała się bardzo szybko.

Podczas gdy możesz zaimplementować ograniczone obrony projektu, aby złapać zwykłe ataki, bardzo zalecane jest, aby zaimplementować bardziej wiarygodne taktyki strony serwera, ponieważ serwer jest najwyższą autorytetem dla każdej bieżącej doświadczenia.

Taktyki projektowe obronne

Podstawowe decyzje o projektowaniu mogą służyć jako "pierwszy krok" środki bezpieczeństwa, aby zniechęcić do wykorzystywania exploitów. Na przykład w grze strzelczo-gry, gdzie gracze zdobywają punkty za zabijanie innych graczy, eksploiter może stworzyć zbiór botów teleportujących się do tego samego miejsca, aby mogły być szybko zabite za punkty. Ze względu na ten potencjalny exploit

PodejściePrzewidywalny wynik
Ścigaj boty, pisząc kod, który próbuje ich wykryć.
Zmniejsz lub całkowicie usuń zyski punktów za zabójstwa na nowo zaspawnowanych graczy.

Podczas gdy projekt obronny oczywiście nie jest doskonałym lub kompletnym rozwiązaniem, może przyczynić się do szerszego podejścia bezpieczeństwa, wraz z mitigacją serwera.

Mitigacja stron serwera

O ile to możliwe, serwer powinien wydać ostateczny wyrok na to, co jest "prawdziwe" i co jest obecnym stanem świata. Klienty mogą oczywiście zapytać serwer o dokonanie zmian lub wykonanie akcji, ale serwer powinien zatwierdzić i zaakceptować każdą z tych zmian/akcji przed wdrożeniem wyników do innych graczy.

Poza niektórymi operacjami fizycznymi zmiany w modelu danych na klienta nie odzwierciedlają się na serwerze, więc główny droga atakowa jest często poprzez wydarzenia sieci, któreś zgłosiłeś za pomocą RemoteEvents i RemoteFunctions. Pamiętaj, że haker, który wykonuje własny kod na swoim klencie, mo

Weryfikacja typu czasu uruchomienia zdalnego

Jedną drogę ataku jest dla atakującego, aby wywołać RemoteEvents i RemoteFunctions z argumentami niezgodnego wpisywać. W niektórych scenariuszach może to powodować błąd kodu na serwerze słuchającym tych zdalnych do błędu w taki sposób, że jest to korzystne dla atakującego.

Podczas używania zdalnych wydarzeń/funkcji możesz zapobiec temu typowi ataku poprzez uwalidowanie typów przekazanych argumentów na serwerze. Moduł t, dostępny tutaj, jest przydatny do sprawdzania typu w ten sposób. Na przykład, załóż

Lokalny skrypt w StarterPlayerScripts

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:WaitForChild("RemoteFunctionTest")
-- Przekaż kolor i pozycję części podczas wzywania funkcji
local newPart = remoteFunction:InvokeServer(Color3.fromRGB(200, 0, 50), Vector3.new(0, 25, 0))
if newPart then
print("The server created the requested part:", newPart)
elseif newPart == false then
print("The server denied the request. No part was created.")
end
Skrypt w ServerScriptService

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:WaitForChild("RemoteFunctionTest")
local t = require(ReplicatedStorage:WaitForChild("t"))
-- Twórz wcześniej weryfikator typu, aby uniknąć niepotrzebnej nadmiernej wydajności
local createPartTypeValidator = t.tuple(t.instanceIsA("Player"), t.Color3, t.Vector3)
-- Utwórz nową część z przekazanymi właściwościami
local function createPart(player, partColor, partPosition)
-- Sprawdź przekazane argumenty
if not createPartTypeValidator(player, partColor, partPosition) then
-- Cicho zwracaj "false", jeśli checkowanie typu nie powiodło się tutaj
-- Podwyższanie błędu bez odliczania może być wykorzystane do spowolnienia serwera
-- Zamiast tego zapewnij opinię klienta!
return false
end
print(player.Name .. " requested a new part")
local newPart = Instance.new("Part")
newPart.Color = partColor
newPart.Position = partPosition
newPart.Parent = workspace
return newPart
end
-- Zwiąż funkcję "createPart()" z wezwaniem funkcji zdalnej
remoteFunction.OnServerInvoke = createPart

Weryfikacja danych

Kolejnym atakiem, który może zainicjować hakerzy, jest wysyłanie technicznie poprawnych typów ale czynią je niezwykle dużymi, długimi lub w inny sposób nieznormalizowanymi. Na przykład, jeśli serwer musi wykonić drogie operacje na łańcuchu, który skala się z długości, haker może wysłać niezwykle duży lub nieznormalizowany łańcuch, aby spowolnić serwer.

Podobnie zarówno inf i NaN będą type() jako 1> number1>, ale obie mogą powodować poważne problemy, jeśli eksploiter wysyłuje je i nie są one prawidłowo przetwarzane poprzez funkcje takie jak obserwuje:


local function isNaN(n: number): boolean
-- NaN nigdy nie jest równy siebie
return n ~= n
end
local function isInf(n: number): boolean
-- Liczba może być -inf lub inf
return math.abs(n) == math.huge
end

Kolejnym powszechnym atakiem, który może wykonać eksploiter, jest wysyłanie tables zamiast Class.Instance . Złożone ładowania mogą imitować to, co byłoby w przeciwnym razie zwykłym odniesieniem do obiektu.

Na przykład, zapewniony z systemem w sklepie w czasie eksperymentu, gdzie dane przedmiotów, takie jak ceny, są przechowywane w NumberValue obiektach, haker może określić wszystkie inne czynniki, wykonując obserwujekroki:

Lokalny skrypt w StarterPlayerScripts

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local itemDataFolder = ReplicatedStorage:WaitForChild("ItemData")
local buyItemEvent = ReplicatedStorage:WaitForChild("BuyItemEvent")
local payload = {
Name = "Ultra Blade",
ClassName = "Folder",
Parent = itemDataFolder,
Price = {
Name = "Price",
ClassName = "NumberValue",
Value = 0, -- Można użyć również negatywnych wartości, co prowadzi do dawania waluty, a nie jej brania!
},
}
-- Wyślij niechciany ładunek na serwer (ten zapis zostanie odrzucony)
print(buyItemEvent:InvokeServer(payload)) -- Wyświetla "false Invalid item provided"
-- Prześlij prawdziwy przedmiot na serwer (ten przedmiot przejdzie!)
print(buyItemEvent:InvokeServer(itemDatafolder["Real Blade"])) -- Outputs "true" and remaining currency if purchase succeeds
Skrypt w ServerScriptService

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local itemDataFolder = ReplicatedStorage:WaitForChild("ItemData")
local buyItemEvent = ReplicatedStorage:WaitForChild("BuyItemEvent")
local function buyItem(player, item)
-- Sprawdź, czy przesłany przedmiot nie jest fałszywy i znajduje się w katalogu ItemData
if typeof(item) ~= "Instance" or not item:IsDescendantOf(itemDataFolder) then
return false, "Invalid item provided"
end
-- Następnie serwer może kontynuować przetwarzanie zakupu w oparciu o poniższy przykładowy przepływ
end
-- Zwiąż funkcję „buyItem()” z wezwaniem funkcji zdalnej
buyItemEvent.OnServerInvoke = buyItem

Wartościowe uwierzytelnienie

Oprócz weryfikacji typy i dane, powinieneś weryfikować wartości przesłane poprzez 2> Class.RemoteEvent|RemoteEvents2> i 5> Class.RemoteFunction|RemoteFunctions5>, zapewniając, że są one poprawne i logiczne

Sklep w trybie bez doświadczenia

Rozważaj system sklepu w grze z interfejsem użytkownika, na przykład menu wyboru produktu z przyciskiem "Kup". Gdy przycisk jest naciśnięty, możesz wejść w RemoteFunction pomiędzy klientem a serwerem, aby złożyć kupować. Jest jednak ważne, aby serwer, najbardziej wiarygodny kierown

Example purchase flow from client to server through a RemoteEvent
Przykładowy płyn zakupu od klienta do serwera poprzez RemoteFunction

Celowanie za pomocą broni

Scenerie walki wymagają szczególnej uwagi na uwalnianie wartości, szczególnie poprzez celowanie i potwierdzenie celowania.

Wyobraź sobie grę, w której gracz może wystrzelić laserowy promień na innego gracza. Zamiast klienta powiadomić serwer, aby zadać obrażenia, powinien powiedzieć serwerowi pozycję źródła strzału i pozycję części/pozycji, którą myśli, że dotknął. Następnie serwer może potwierdzić obserwuje:

  • Pozycja, którą klient zgłasza strzela z jest bliska charakterowi gracza na serwerze. Uwaga, że serwer i klient będą się nieco różnić ze względu na opóźnienie, więc dodatkowe tolerancja będzie wymagać zastosowania.

  • Pozycja, którą raportuje klient, uderzenie jest rozsądnie blisko pozycji części , którą raportuje, na serwerze.

  • Nie ma statycznych przeszkód między pozycją, którą klient zgłasza, że strzela, a pozycją, którą klient zgłasza, że strzela. Ta sprawdza zapewnia, że klient nie próbuje strzelać poprzez ściany. Uwaga, że powinno to tylko sprawdzać geometrię statyczną, aby uniknąć zgłaszanych przez klatkę piersiową rzutów. Dodatkowo można zaimplementować dalsze weryfikacje stron serwera jako następuje:

  • Śledź, kiedy gracz po raz ostatni wystrzelił swoją bronią i potwierdź, aby upewnić się, że nie strzela zbyt szybko.

  • Śledź ilość amunicji każdego gracza na serwerze i potwierdź, że grający strzelający ma wystarczająco amunicji, aby wykonać atak broni.

  • Jeśli wdrożyłeś zespoły lub system walki z botami, potwierdź, że hit character jest wróg, przeciwnik, nie członkiem zespołu.

  • Potwierdź, że gracz trafiony jest żywy.

  • Przechowuj stan uzbrojenia i gracza na serwerze i potwierdź, że nie zablokowano gracza do strzelania przez bieżącą akcję, taką jak ponowne ładowanie lub stan biegu.

Manipulacja magazynem danych

W doświadczeniach używając DataStoreService do zapisywania danych gracza, oszuści mogą wykorzystać nieprawidłowe dane i inne nieoznakowane metody, aby zapobiec, aby DataStore zapisał prawidłowo. To może być szczególnie wykorzystywane w doświadczeniach z wyposażenieprzed

Upewnij się, że wszystkie działania wykonane za pośrednictwem RemoteEvent lub RemoteFunction, które wpływają na dane gracza z wejścia klienta, są zsanizowane w oparciu o obserwujekwestie:

  • Wartości Class.Instance nie można zapisać w Class.DataStore i nie powiodą się. Użyj weryfikacji typu aby zapobiec temu.
  • DataStores mają ograniczenia danych . Strings długości dowolnej długości powinny być sprawdzane i/lub ograniczone, aby to uniknąć, wraz z zapewnieniem, że nie można dodać tabelom dowolnych nieskończonych kluczy.
  • Indeksy tabel nie mogą być NaN lub nil . Przez przeglądarkę przetwarzane są wszystkie tabely i sprawdza się, czy wszystkie indeksy są poprawne.
  • DataStores może otrzymywać tylko poprawne znaki UTF-8, więc powinieneś upewnić się, że wszystkie łańcuchy dostarczone przez klienta poprzez

Dystansowe sterowanie

Jeśli klient jest w stanie zrobić, aby twój serwer wykonał kosztowną operację obliczeniową lub uzyskał dostęp do usługi ograniczonej czasowo, takiej jak DataStoreService poprzez RemoteEvent , jest istotne, aby zaimplementować ograniczanie stóp, aby upewnić

Weryfikacja ruchu

Dla doświadczeń konkurencyjnych można chcieć zidentyfikować ruchy postaci gracza na serwerze, aby upewnić się, że nie teleportują się po mapie lub nie przesuwają się szybciej niż akceptowalne.

  1. W ciągu 1 sekundy sprawdź nową lokalizację znaku z wcześniej zapisanej lokalizacji.

    Image showing moving character's position on a straight path in increments of 1 second
  2. Określ maksymalną zmianę "tolerowalności" w odległości w oparciu o WalkSpeed (studs/s) pojedynczo przez ~1,4, aby umożliwić trochę elastyczności wobec serwerowej latencji. Na przykład, przy domyślnym WalkSpeed 16, maksymalna zmiana

    Image showing tolerable change in distance based on character's walk speed
  3. Porównaj rzeczywisty dystrybucja dystansu przeciwko dystrybucji tolerowalnej i postępuj zgodnie z poniższym:

    • Dla do zniesienia Delta, zapisz nową lokalizację postaci w przygotowaniu do następnego zwiększonego sprawdzać.
    • Dla nieoczekiwanego lub nieznośnego Delta (potencjalne wykorzystanie prędkości/teleportacji):
      1. Zwiększ wartość "liczby przestępstw" dla gracza względem kary za "źle pozytywne" wynikające z ekstremalnej latencji serwera lub innych czynników niezawinienia.
      2. Jeśli dochodzi do dużej liczby naruszeń w ciągu 30-60 sekund, Kick() gracza z doświadczenia całkowicie; w przeciwnym razie zresetuj liczbę naruszeń. Uwaga, że przy okazaniu kary za oszustwo należy zapisać wydarzenie, abyś mógł śledzić, ile osób jest dotkniętych.