Roblox sử dụng một hệ thống vật lý phân tán trong đó khách hàng có quyền sở hữu trên mô phỏng vật lý của các đối tượng trong điều khiển của họ, thường là nhân vật của người chơi và các đối tượng bị kết bằng gần nh
Nhân tập, điều này có nghĩa là một kẻ tấn công có kỹ năng có thể thi hành mã để gian lận trong trò chơi của bạn, bao gồm:
- Dịch chuyển nhân vật của riêng họ xung quanh địa điểmđó.
- Đang khởi động unsecured RemoteEvents hoặc gọi RemoteFunctions, chẳng hạn như để cho phép bản thân mình nhận các món đồ mà không kiếm được chúng.
- Điều chỉnh tốc độ di chuyển của nhân vật của họ WalkSpeed để nó di chuyển rất nhanh.
Mặc dù bạn có thể thực hiện các bản phòng thủ thiết kế giới hạn để bắt các cuộc tấn công thông thường, nhưng rất được khuyến nghị bạn thực hiện nhiều lời khuyên bảo vệ máy chủ hơn, vì máy chủ là oẩn quyền tối thượng cho bất kỳ trải nghiệm đang chạy.
Chiến thuật thiết kế phòng thủ
Các quyết định thiết kế cơ bản có thể phục vụ như "bước đầu" các biện pháp an toàn để ngăn chặn các lỗi. Ví dụ, trong một trò chơi bắn tỉa nơi người chơi nhận điểm cho việc giết những người chơi khác, một nhà lập trình có thể tạo
Pendekatan | Kết quả có thể dự đoán |
---|---|
Theo dõi các bốt bằng cách viết mã nó cố gắng để phát hiện chúng. | |
Giảm hoặc loại bỏ hoàn toàn lợi nhuận điểm cho các lần giết người đã được tạo mới. |
Trong khi thiết kế phòng thủ rõ ràng không phải là một giải pháp hoàn hảo hoặc toàn diện, nó có thể đóng góp vào một kế tiếp của bảo mật, cùng với giải pháp bên máy chủ hóa giải.
Mitigate pih面 của máy chủ
Nhiều như có thể, máy chủ server nên đưa ra phán quyết cuối cùng về những gì là "đúng" và những gì là trạng thái hiện tại của thế giới. Clients có thể, tất nhiên, yêu cầu máy chủ làm những thay đổi hoặc thực hiện một hành động, n
Ngoại trừ một số hoạt động vật lý nhất định, thay đổi về mô hình dữ liệu trên client không bao giờ sao chép đến máy chủ, vì vậy con đường tấn công chính là thông qua các sự kiện mạng bạn đã tuyên bố với Class.RemoteEvent|
Xác minh kiểu thời gian thực tế
Một con đường tấn công là cho một nhà xâm nhập gọi RemoteEvents và RemoteFunctions với những lý do lỗi của đánh máykhông đúng. Trong một số tình huống, điều này có thể gây ra mã trên máy chủ đang lắng nghe những remote nà
Khi sử dụng các sự kiện/chức năng từ xa, bạn có thể ngăn chặn loại tấn công này bằng cách xác minh các loại của các tham số đã được truyền trên máy chủ. Modul
LocalScript trong StarterPlayerScripts
local ReplicatedStorage = game:GetService("ReplicatedStorage")local remoteFunction = ReplicatedStorage:WaitForChild("RemoteFunctionTest")-- Đổi màu và vị trí của bộ phận khi gọi chức nănglocal newPart = remoteFunction:InvokeServer(Color3.fromRGB(200, 0, 50), Vector3.new(0, 25, 0))if newPart thenprint("The server created the requested part:", newPart)elseif newPart == false thenprint("The server denied the request. No part was created.")end
Script trong ServerScriptService
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:WaitForChild("RemoteFunctionTest")
local t = require(ReplicatedStorage:WaitForChild("t"))
-- Tạo validator kiểu trước để tránh Overhead không cần thiết
local createPartTypeValidator = t.tuple(t.instanceIsA("Player"), t.Color3, t.Vector3)
-- Tạo một phần mới với các thuộc tính đã được chuyển
local function createPart(player, partColor, partPosition)
-- Kiểm tra các tham số đã được truyền
if not createPartTypeValidator(player, partColor, partPosition) then
-- Trở lại im lặng "false" nếu kiểm tra kiểm tra type thất bại ở đây
-- Tăng một lỗi mà không có thời gian đếm ngược có thể bị lạm dụng để làm cho máy chủ bị trì hoãn
-- Cung cấp phản hồi của khách hàng thay vào đó!
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
-- Gắn "createPart()" vào hành động của chức năng xa
remoteFunction.OnServerInvoke = createPart
Xác minh dữ liệu
Một cuộc tấn công khác mà các kẻ tấn công có thể thực hiện là gửi các loại hợp lệ kỹ thuật số nhưng làm cho chúng rất lớn, dài hoặc bị lỗi nhưng không đúng. Ví dụ, nếu máy chủ phải thực hiện một hoạt động đắt tiền trên một chuỗi có
Tương tự, cả inf và NaN sẽ type() như 1> number1>, nhưng cả hai có thể gây ra các vấn đề lớn nếu một kẻ tấn công gửi chúng và chúng không được xử lý đúng cách thông qua các chứ
local function isNaN(n: number): boolean
-- NaN không bao giờ là bằng chính mình
return n ~= n
end
local function isInf(n: number): boolean
-- Số có thể là -inf hoặc inf
return math.abs(n) == math.huge
end
Một cuộc tấn công phổ biến khác mà các kẻ tấn công có thể sử dụng là gửi tables vào chỗ của một Instance . Các hành tây phức tạp có thể sao chép những gì sẽ là một tham chiếu đối tượng bình thường khác.
Ví dụ, cung cấp với một trong kinh nghiệm shop hệ thống nơi dữ liệu mặt hàng như giá được lưu trong NumberValue đối tượng, một kẻ lừa đảo có thể vượt qua tất cả các kiểm tra khác bằng cách thực hiện những hành động theo dõi:
LocalScript trong 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, -- Giá trị âm cũng có thể được sử dụng, kết quả là cho phép bạn cho tiền tệ thay vì lấy nó!},}-- Gửi malicious payload đến máy chủ (điều này sẽ bị từ chối)print(buyItemEvent:InvokeServer(payload)) -- Hiện thị "falseInvalid item provided"-- Gửi một món đồ thực sự đến máy chủ (điều này sẽ đi qua!)print(buyItemEvent:InvokeServer(itemDatafolder["Real Blade"])) -- Outputs "true" and remaining currency if purchase succeeds
Script trong ServerScriptService
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local itemDataFolder = ReplicatedStorage:WaitForChild("ItemData")
local buyItemEvent = ReplicatedStorage:WaitForChild("BuyItemEvent")
local function buyItem(player, item)
-- Kiểm tra nếu món đồ đã được chuyển và nó ở thư mục ItemData
if typeof(item) ~= "Instance" or not item:IsDescendantOf(itemDataFolder) then
return false, "Invalid item provided"
end
-- Máy chủ sau đó có thể tiến hành xử lý mua hàng dựa trên ví dụ dòng chảy dưới đây
end
-- Gắn "buyItem()" vào hành động của chức năng xa cầm
buyItemEvent.OnServerInvoke = buyItem
Xác định giá trị
Ngoài việc xác minh các loại hợp lệ typ và dữ liệu data, bạn cần xác minh các giá trị đã được truyền qua Class.RemoteEvent|RemoteEvents và 1> Class.RemoteFunction
Cửa hàng trong kinh nghiệm
Hãy xem xét một hệ thống trong trải nghiệm với một giao diện người dùng, ví dụ như một menu lựa chọn sản phẩm với nút "Mua" . Khi nút được nhấn, bạn có thể gọi một RemoteFunction giữa client và server để yêu c
Mục tiêu vũ khí
Các tình huống chiến đấu yêu cầu sự chú ý đặc biệt về việc xác minh giá trị, đặc biệt là qua việc ngắm bắn và xác minh ngắm bắn.
Hãy tưởng tượng một trò chơi nơi một người chơi có thể bắn một tia laser vào một người chơi khác. Thay vì nói rằng khách hàng cho máy chủ biết ai để hại chết, nó nên nói với máy chủ vị trí nguồn của cú đá và vị trí mà nó nghĩ rằng nó đã đánh. Máy chủ
Vị trí mà client báo cáo bắn từ gần nhân vật của người chơitrên máy chủ. Lưu ý rằng máy chủ và client sẽ có sự khác biệt nhỏ do thời gian trễ, vì vậy sự kiên nhẫn thêm sẽ cần được áp dụng.
Vị trí mà client báo cáo đánh gần vị trí của phần mà client đánh, trên máy chủ.
Không có rào chắn statis giữa vị trí mà client báo cáo bắn từ và vị trí mà client báo cáo bắn tới. Điều này kiểm tra để chắc chắn rằng client không đang cố gắng bắn qua tường. Ghi nhớ rằng điều này chỉ kiểm tra geometri statis để đảm bảo các cú đá không bị từ chối do thời gian trễ. Ngoài ra , bạn có thể muốn thực hiện thêm các lỗi xác minh bên máy chủ như sau:
Theo dõi khi người chơi cuối cùng bắn vũ khí của họ và xác minh để đảm bảo họ không bắn quá nhanh.
Theo dõi số đạn của mỗi người chơi trên máy chủ và xác nhận rằng một người chơi đang chơi đủ đạn để thực hiện cuộc tấn công vũ khí.
Nếu bạn đã thực hiện đội hoặc một hệ thống chiến đấu "người chơi chống lại bốt", xác nhận rằng nhân vật trúng là kẻ thù, không phải là đồng đội.
Xác nhận người chơi đang sống.
Lưu trạng thái vũ khí và người chơi trên máy chủ và xác nhận rằng một người chơi đang không bị chặn bởi một hành động hiện tại như quét hoặc trạng thái như chạy.
Lưu trữ dữ liệu
Trong các trải nghiệm sử dụng DataStoreService để lưu dữ liệu người chơi, kẻ lừa đảo có thể tận dụng những dữ liệu bị sai rồi, và những phương pháp khác nhiều hơn, để ngăn chặn một Class.Data
Đảm bảo rằng bất kỳ hành động thực hiện thông qua một RemoteEvent hoặc RemoteFunction ảnh hưởng đến dữ liệu người chơi với sự đầu ghi của khách hàng dựa trên những gì được đề xuất theo dõi:
- Instance giá trị không thể được serialize thành một DataStore và sẽ thất bại. Sử dụng kiểm tra kiểu để ngăn chặn điều này.
- DataStores có giới hạn dữ liệu . Các dòng dữ liệu bất kỳ phải được kiểm tra và/hoặc được giới hạn để tránh điều này, cùng với việc đảm bảo các dòng dữ liệu ngẫu nhiên không thể được thêm vào các bảng bởi khách hàng.
- Các chỉ mục bảng không thể là NaN hoặc nil . Items trên tất cả các bảng đã được chuyển qua khách hàng và xác minh tất cả các chỉ mục là hợp lệ.
- DataStores chỉ có thể chấp nhận các kí tự UTF-8 hợp lệ, vì vậy bạn nên kiểm tra tất cả các chuỗi đư
Throttling từ xa
Nếu một khách hàng có thể làm cho máy chủ của bạn hoàn thành một hoạt động có chi phí cao tính toán, hoặc truy cập một dịch vụ hạn chế tỷ lệ như DataStoreService qua một dịch vụ RemoteEvent
Xác định vị trí di chuyển
Đối với những trải nghiệm cạnh tranh, bạn có thể muốn xác minh các chuyển động nhân vật trên máy chủ để đảm bảo chúng không đang dịch chuyển xung quanh bản đồ hoặc di chuyển nhanh hơn mức độ chấp nhận.
Trong những tăng trưởng 1 giây, kiểm tra vị trí mới của nhân vật so với một vị trí đã lưu trước đó.
Xác định một thay đổi "độ dốc" tối đa dựa trên tính năng WalkSpeed (studs/giây) của nhân vật, nhân hệ số ~1,4 để cho phép một số dung lượng nào đó chống lại thời gian tr
So sánh sự thật dịch chuyển đối xứng chống lại dịch chuyển dung nham và tiến hành như sau:
- Đối với một đ Delta có thể chấp kiểm tra, lưu vị trí mới của nhân vật trong khoảng thời gian chờ tăng thêm.
- Đối với một Delta bất ngờ hoặc không thể chịu đựng (lỗi tốc độ/lỗi dịch chuyển):
- Tăng một giá trị "number of offenses" riêng cho người chơi, so với việc trừng phạt họ vì một "positive false" kết quả từ thời gian trễ cực đoan hoặc các yếu tố không khai thác khác.
- Nếu xảy ra một loạt lớn các tội ác trong một thời gian dài từ 30-60 giây, Kick() người chơi từ trải nghiệm hoàn toàn; nếu không, thiết lập lại số lần tội ác. Lưu ý rằng khi kick một ngườ