กลยุทธ์ด้านความปลอดภัยและการป้องกัน

*เนื้อหานี้แปลโดยใช้ AI (เวอร์ชัน Beta) และอาจมีข้อผิดพลาด หากต้องการดูหน้านี้เป็นภาษาอังกฤษ ให้คลิกที่นี่

Roblox ใช้ ระบบฟิสิกส์แบบจัดการ ในการที่ลูกค้ามีสิทธิ์เป็นเจ้าของวัตถุในการควบคุมของพวกเขา โดยปกติจะเป็นตัวละครของผู้เล่นและวัตถุที่ไม่มีอานุภ

โดยรวมนี่หมายถึงว่าผู้โจมตีที่มีทักษะสามารถประมาทในการประมาทรหัสในเกมของคุณ รวมถึง:

  • การเริ่มต้นเกมของตัวเอง
  • การยิงที่ไม่มีความปลอดภัย RemoteEvents หรือการเรียกใช้ RemoteFunctions เช่นเพื่อให้ตัวเองได้รับรางวัลโดยไม่ต้องสร้างพวกเขา
  • ปรับค่า WalkSpeed ของตัวละครของพวกเขาให้เร็วขึ้น

ในขณะที่คุณสามารถใช้ป้องกันการออกแบบจำกัดเวลาเพื่อจับการโจมตีทั่วไปได้ แต่มีความแนะนำอย่างมากที่คุณจะต้องใช้มาตรการป้องกันด้านเซิร์ฟเวอร์ที่เชื่อถือได้มากขึ้น เนื่องจากเซิร์ฟ

กลยุทธ์การออกแบบที่ป้องกัน

การตัดสินใจขั้นพื้นฐานสามารถให้เป็นมาตรการรักษาความปลอดภัย "ขั้นต้น" เพื่อป้องกันการโจมตี โดยเฉพาะอย่างยิ่งในเกมยิงที่ผู้เล่นได้รับคะแนนสำหรับการฆ่าผู้เล่นค

ใกล้ชิดผลลัพธ์ที่คาดเดาได้
ตามล่าบอทโดยการเขียนโค้ดที่พยายามตรวจจับพวกเขา
ลดหรือลบการเพิ่มจุดสูงสุดสำหรับการฆ่าผู้เล่นใหม่

ขณะที่การออกแบบที่ป้องกันอย่างชัดเจนไม่ใช่วิธีการป้องกันที่สมบูรณ์หรือครอบคลุม, มันสามารถมีส่วนร่วมในการประยุกต์การรักษาความปลอดภัยที่กว้างขวาง, พร้อมกับ การป้องกันด้านเซิร์ฟเวอร์

การหลบหลีกด้านเซิร์ฟเวอร์

มากที่สุดเท่าที่จะเป็นไปได้, เซิร์ฟเวอร์ เซิร์ฟเวอร์ แอ็คชัน"จริง" และสถานะปัจจุบันของโลก ลูกค้าสามาร

ยกเว้นการดำเนินการทางกายภาพบางอย่าง การเปลี่ยนแปลงในแบบข้อมูลของลูกค้าไม่สามารถเลียนแบบไปยังเซิร์ฟเวอร์ได้ ดังนั้นเส้นทางการโจมตีหลักจะ

การตรวจสอบว่า Remote Runtime Type ถูกต้อง

เส้นทางการโจมตีหนึ่งเป็นเส้นทางสำหรับผู้โจมตีที่จะเรียก RemoteEvents และ RemoteFunctions พิมพ์ในบางสถานการณ์นี่อาจทำให้โค้

เมื่อใช้งานระยะไกลเหตุการณ์/การใช้งาน, คุณสามารถป้องกันประเภทของการโจมตีนี้โดยการยืนยันว่า ชนิด ของอา

สคริปต์ใน StarterPlayerScripts

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:WaitForChild("RemoteFunctionTest")
-- ส่งสีและตำแหน่งของส่วนผ่านเมื่อเรียกใช้งาน
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
สคริปท์ใน ServerScriptService

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:WaitForChild("RemoteFunctionTest")
local t = require(ReplicatedStorage:WaitForChild("t"))
-- สร้างตัวตรวจสอบประเภทล่วงหน้าเพื่อหลีกเลี่ยงความเสียประสิทธิภาพที่ไม่จำเป็น
local createPartTypeValidator = t.tuple(t.instanceIsA("Player"), t.Color3, t.Vector3)
-- สร้างส่วนใหม่ด้วยคุณสมบัติที่ผ่าน
local function createPart(player, partColor, partPosition)
-- ตรวจสอบว่ามีข้อมูลผ่านหรือไม่
if not createPartTypeValidator(player, partColor, partPosition) then
-- กลับไปที่ "ใช่" หากผิดพลาดในการตรวจสอบ
-- การเพิ่มข้อผิดพลาดโดยไม่มีคูลดาวน์สามารถโดนลอบโจมตีเพื่อบังคับให้เซิร์ฟเวอร์ติดขัด
-- ให้ความคิดเห็นของลูกค้าแทน!
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
-- ผูก "สร้างPart()" กับคืนของระบบ
remoteFunction.OnServerInvoke = createPart

การตรวจสอบข้อมูล

การโจมตีอื่นที่ผู้โจมตีอาจเปิดตัวคือการส่ง ชนิดที่ถูกต้องตามมาตรฐาน แต่ทำให้พวกเขาใหญ่มาก, ยืดเยื้อหรืออย่างอื่นผิดปกติ เช่น, หากเซิร์ฟเวอร์ต้องประมวลผลก

เช่นเดียวกัน, ทั้ง inf และ NaN จะ type() เป็น 1> number1> แต่ทั้งสองสามารถสร้างปัญหาใหญ่หากผู้โจมตีส่งพวกเขาและพวกเขาไม่ได้รับกา


local function isNaN(n: number): boolean
-- NaN ไม่เคยเท่ากับตัวเอง
return n ~= n
end
local function isInf(n: number): boolean
-- ตัวเลขอาจเป็น -inf หรือ inf
return math.abs(n) == math.huge
end

การโจมตีที่พบบ่อยอื่น ๆ ที่ผู้โจมตีอาจใช้มีการส่ง tables ในที่ส่งของ Instance คลังโหลดขนาดใหญ่สามารถเลียนแบบสิ่งที่จะเป็นปกติอย่างไรก็ตาม

เช่นเดียวกับระบบ ในร้านค้าประสบการณ์ ที่มีข้อมูลรายการเช่นราคาถูกเก็บไว้ใน NumberValue กำลังติดตาม:

สคริปต์ใน 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, -- ค่าเชิญเสมอสามารถใช้ได้เชิญสกุลเงินแทนที่จะรับ!
},
}
-- ส่งข้อมูลผิดพลาดไปยังเซิร์ฟเวอร์ (นี่จะถูกปฏิเสธ)
print(buyItemEvent:InvokeServer(payload)) -- ออก "ไม่ ได้มีรายการที่ให้"
-- ส่งรายการจริงไปยังเซิร์ฟเวอร์ (นี่จะผ่าน!)
print(buyItemEvent:InvokeServer(itemDatafolder["Real Blade"])) -- Outputs "true" and remaining currency if purchase succeeds
สคริปท์ใน ServerScriptService

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local itemDataFolder = ReplicatedStorage:WaitForChild("ItemData")
local buyItemEvent = ReplicatedStorage:WaitForChild("BuyItemEvent")
local function buyItem(player, item)
-- ตรวจสอบว่ารายการที่ผ่านไม่ได้ปลอมและอยู่ในไฟล์ ItemData
if typeof(item) ~= "Instance" or not item:IsDescendantOf(itemDataFolder) then
return false, "Invalid item provided"
end
-- ตัวเซิร์ฟเวอร์จะจัดการการซื้อต่อได้ขึ้นอยู่กับกระบวนการเชิญชวนด้านล่าง
end
-- ผูก "buyItem()" กับคอลล์แบ็คระยะไกล
buyItemEvent.OnServerInvoke = buyItem

การตรวจสอบค่า

นอกจากการยืนยัน ชนิด และ ข้อมูล แล้ว คุณยังควรยืนยัน มูลค่า ที่ผ่านผ่าน 1> Class.RemoteEvent|RemoteEvents1>

ร้านค้าในประสบการณ์

พิจารณาระบบร้านค้าในประสบการณ์ที่มี UI สําหรับผู้ใช้ เช่น การเลือกผลิตภัณฑ์ที่มีปุ่ม "ซื้อ" เมื่อปุ่มถูกกด คุณสามารถเรียกใช้

Example purchase flow from client to server through a RemoteEvent
การซื้อตัวอย่างการซื้อจากลูกค้าไปยังเซิร์ฟเวอร์ผ่าน RemoteFunction

การเล็งอาวุธ

สถานการณ์การต่อสู้ต้องให้ความสนใจเป็นพิเศษเกี่ยวกับการยืนยันมูลค่าโดยเฉพาะผ่านการเล็งและการตรวจสอบว่าตรง

จินตนาการเกมที่ผู้เล่นสามารถยิงลำแสงเลเซอร์ไปยังผู้เล่นอื่น แทนที่จะบอกเครื่องมือว่าจะทำให้เสียหาย มันควรบอกเครื่องมือว่าตำแหน่งเดิมของกระสุนและสถานที่/ตําแหน่งที่ม

  • ตําแหน่งที่ลูกค้ารายงานว่า ยิงจาก ใกล้กับตัวละครของผู้เล่นในเซิร์ฟเวอร์ หมายเหตุว่าเซิร์ฟเวอร์และลูกค้าจะแตกต่างกันเล็กน้อยเนื่องจากความแลคของเซิร์ฟเวอร์ดังนั้นความอดทนเพิ่มเต

  • ตําแหน่งที่ลูกค้ารายงานว่า ตี ใกล้กับตําแหน่งของ ส่วน ที่ลูกค้ารายงานว่าตีบนเซิร์ฟเวอร์

  • ไม่มีอุปสรรคที่คงที่ระหว่างตำแหน่งที่ลูกค้ารายงานยิงจากและตำแหน่งที่ลูกค้ารายงานยิงไป สิ่งนี้จะรับประกันว่าลูกค้าไม่ได้พยายามที่จะยิงผ่านผนัง นอกจากนี้ คุณอาจต้องการให้ใช้งานการตรวจสอบของเซิร์ฟเวอร์เพิ่มเติมด้วยวิธีต่อไปนี้:

  • ติดตามเมื่อผู้เล่นยิงอาวุธของพวกเขาครั้งสุดท้ายและรับรองเพื่อให้แน่ใจว่าพวกเขายิงเร็วเกินไป

  • ติดตามจำนวนกระสุนของผู้เล่นแต่ละรายบนเซิร์ฟเวอร์และยืนยันว่าผู้เล่นยิงมีกระสุนเพียงพอเพื่อดำเนินการโจมตีอาวุธ

  • หากคุณใช้ ทีม หรือระบบต่อสู้ของ "ผู้เล่น vs บอท" ยืนยันว่าตัวละครที่ติดสถานะ "ศัตรู" ไม่ใช่เพื่อนร่วมทีม

  • ยืนยันว่าผู้เล่นที่โดนยิงมีชีวิตอยู่

  • เก็บสถานะอาวุธและผู้เล่นบนเซิร์ฟเวอร์ และยืนยันว่าผู้เล่นที่กำลังเล่นไม่ได้ถูกบล็อกโดยการกระทําปัจจุบันเช่นการรีโหลดหรือสถานะเช่นการวิ่ง

การจัดการข้อมูล

ในประสบการณ์ที่ใช้ DataStoreService เพื่อบันทึกข้อมูลผู้เล่น ผู้โจมตีอาจใช้วิธีการ ข้อมูลของผู้เล่น ที่ไม่ถูกต้อง และวิธีการที่ซ่อนอย

ตรวจสอบให้แน่ใจว่าการกระทําใด ๆ ที่ดําเนินการผ่าน RemoteEvent หรือ RemoteFunction กำลังติดตาม:

  • Instance ค่าไม่สามารถถูกเรียกใน DataStore และจะล้มเหลว ใช้ การตรวจสอบประเภท เพื่อป้องกันสิ่งนี้
  • DataStores มี ขีดจำกัดข้อมูลของข้อมูลของข้อมูลของข้อมูลของข้อมูลของข้อมูลของข้อมูลของข้อมูลของข้อมูลของข้อมูลของข้อมูลของข้อมูลของข้อมูลของข้อมูลของข้อมูลของข้อ
  • ดัชนีตารางไม่สามารถเป็น NaN หรือ nil ได้ เรียกใช้ทุกตารางที่ผ่านโดยลูกค้าและตรวจสอบให้แน่ใจว่าดัชนีทั้งหมดเป็นไปตามมาตรฐาน
  • DataStores สามารถยอมรับตัวอักษร UTF-8 เท่านั้นดังนั้นคุณจึงควรสแน็ปได้ว่

การควบคุมระยะไกล

หากลูกค้าสามารถทำให้เซิร์ฟเวอร์ของคุณสามารถทำงานได้อย่างคุ้มค่าหรือเข้าถึงบริการราคาจำกัดเวลาเช่น DataStoreService ผ่าน Class.RemoteEvent

การตรวจสอบการเคลื่อนที่

สำหรับประสบการณ์ที่แข่งขันได้ คุณอาจต้องการยืนยันการเคลื่อนไหวของตัวละครผู้เล่นบนเซิร์ฟเวอร์เพื่อให้แน่ใจว่าพวกเขาไม่ได้เคลื่อนที่ไปรอบ ๆ แผนที่หรือไม่ได้เคลื่อนที่เร็วเกินไป

  1. ในระยะเวลา 1 วินาที ตรวจสอบตำแหน่งใหม่ของตัวละครเมื่อเปรียบเทียบกับสถานที่ที่เคยเก็บไว้ก่อนหน้านี้

    Image showing moving character's position on a straight path in increments of 1 second
  2. กำหนดการเปลี่ยนแปลง "ทอลเลอร์เบิล" สูงสุดในระยะทางโดยใช้ค่า WalkSpeed (สตั๊ดต่อวินาที) ของตัวละคร โดยประมาณ ~1.4 เพ

    Image showing tolerable change in distance based on character's walk speed
  3. เปรียบเทียบระยะทางจริงกับระยะทางที่อดทนได้และดำเนินการต่อไปด้วยวิธีต่อไปนี้:

    • สำหรับดีลตาของเดลต้าที่เก็บได้ จัดเก็บตำแหน่งของตัวละครใหม่ในการเตรียมพร้อมสำหรับการเพิ่มขนาดต่อไป
    • สำหรับดีลตาขนาดต่างๆ ที่ไม่คาดคิดหรือไม่อดทน (การโจมตีความเร็ว / การเคลื่อนย้ายที่อาจเกิดขึ้น):
      1. เพิ่ม "จำนวนการกระทำผิด" ค่าสำหรับผู้เล่นโดยเฉพาะสำหรับผู้ต้องโทษสำหรับ "การละเมิดที่เกิดขึ้นจากความแลคของเซิร์ฟเวอร์ที่เกินไปหรือปัจจัยการไม่เอาน่านอาชญกรรมอื่น ๆ ที่ไม่ใช่การโจมตี
      2. หากเกิดอาชญากรรมขนาดใหญ่เกิดขึ้นในระยะเวลา 30-60 วินาที Kick() ผู้เล่นจากประสบการณ์ทั้งหมด; อย่างไรก็ตาม เมื่อเตะผู้เล่นเพื่อแส