What should I NOT do when making exploit protection?


#6

You may want to look into this thread to check a player’s ping. It has several methods which are mostly optimal

Best way to get player ping?


#7

Never rely on client-based anti-exploit systems. Everything on the client can be modified by the exploiter, including the anti-exploits. Always do server checks, since exploiters don’t have access to that. Using PrivateModule isn’t necessary per-se since nobody (other than the devs) can access server-side content anyways.


#9

When you add remote event security, don’t kill people for sending fake values over; it could be an issue with your LocalScript that makes it fire bad data. Just ignore the exploiter’s request or add a cool down before they’re allowed to send another request or whatever.


#10

For god mode, I wouldn’t bother making your own exploit protection because roblox core scripts now automatically respawn most common godmode exploiters.


#11

Their is a lot of things that you should and shouldn’t do when making exploit protection.

  • The general rule with making any game is to never trust the client. This rule applies to making exploit protection because the client can modify the exploit protection.

  • Try to avoid using RemoteFunction because the client can tamper with the information sent back to the server. If you do use these make sure you have checks on the information sent back to the server.

  • When checking for exploits you shouldn’t make loops that run every millisecond because that will make your game lag a lot more. Instead make the loops run every 3 seconds for example.

  • Each time the clients data saves you should check it (or sends information to the datastore). If you have a money system in your game for example, you can check how much money the client has made over a certain amount of time. If the money seems to be too much then they must be exploiting.

Here is a useful topic about exploits: Exploiting Explained


#12

Alright, first of all you need to assume that the client has tampered the data that is sending back to the server. Implement sanity checks and ensure that the server validates every request.

Since some others have sent some good tips, I am just gonna add that your checks must not depend on the player’s connection quality. Server-sided movement checks, bullet checks and so on that depend on the player’s connection may raise false-positives.


#13

Idea:


do
	local ffc					= game.FindFirstChild
	local wfc					= game.WaitForChild
	local replicatedstorage				= game:GetService("ReplicatedStorage")
	
	local remote				= wfc(replicatedstorage, "RemoteEvent")
	local bounce				= wfc(replicatedstorage, "BounceEvent")
	local key					= 1
	local functions				= {}
	local playerkeys				= {}
	local players				= {}
	
	local function getkey(player)
		if not playerkeys[player] then
			playerkeys[player] = 1
		end
		playerkeys[player] = 3041353153 * playerkeys[player] % 30481353564
		return playerkeys[player]
	end
	
	function network.send(player, ...)
		--if players[player] then
			remote:FireClient(player, ...)
		--end
	end
	
	function network.bounce(player, key, name, ...)
		--print("bounce")
		--remote:FireAllClients(name, ...)
		local currentkey = playerkeys[player]
		
		if key == getkey(player) then
			--print("key")
			for i = 1, #players do
				if players[i] ~= player then
					remote:FireClient(players[i], name, ...)
				end
			end
		else
			playerkeys[player] = currentkey
		end
	end
	
	function network.receive(player, key, name, ...)
		if key == getkey(player) then
			local func = functions[name]
			if func then
				return func(...)
			end
		else
			--kick player for hacking
			player:Kick("You just got kicked for hacking")
		end
	end
	
	function network.add(name, func)
		functions[name] = func
	end
	
	remote.OnServerEvent:connect(network.receive)
	bounce.OnServerEvent:connect(network.bounce)
	
	game.Players.PlayerAdded:connect(function(player)
		players[#players+1] = player
	end)
	
	game.Players.PlayerRemoving:connect(function(player)
		for i = 1, #players do
			if players[i] == player then
				table.remove(players, i)
			end
		end
	end)
end

*Basically --> client key ~= client key on server --> Kick player… If the remote event is executed via exploited tools, it will kick the player… In my own game, the client key keeps changing like every 0.1 seconds, so I feel like it’s near impossible to try and fake a remote event request outside the script.

In my own setup, I have a few functions relating to remote events and their functionality.


#14

Please put your code in code blocks, so it is easier to read.

3 ` symbols lua

–code here

another 3 ` symbols

--code here

#15

A key system does not work. Exploiters can intercept any and all information sent to or from remotes. They can see a few requests or look at your code, figure out the formula, and fake requests. Alternatively, they can edit requests while they’re in transit. See Is it possible for exploiters to intercept Remotes, and possibly event edit them?.


#16

Phantom Forces uses a key system for their remote events - meaning that it probably works.


#17

Security through obscurity is not real security. Things like key systems or encrypting traffic are only temporary and fragile ways to stop exploiters, considering the exploiter has full access to what happens on their client.


#18

Do you have any suggestions on how to provide more “security” to remote events? (ignoring the key system idea)


#19

Server-sided checks and server authorization. Everything else is pretty much futile and a waste of time.


#20

To further explain this, almost every remote you create should be easy to sanity check and authorise server side. This can literally be as simple as checking a player’s position or whether they have a gamepass (server side).


#21

When making my Anti Cheats I do it on the server and check the users ping. You can then get the average ping that user has within the last minute or so and compare if there movement speed is abnormal.

It’s a bit more advanced then this in order to prevent false positives, but that’s the basic idea.


#22

This is a little off-topic, but relating to exploit protection:

Example:

Client-Side: Let’s pretend that you want to fire a bullet

remote event arguments to server (player, bullet direction / or mouse hit, player position)

Can the server really trust the player position sent?^

Or should the server use it’s version of the player’s position? (If yes, wouldn’t players see a little latency between the initial point from where they wanted to fire from?)


#23

Guns are by far the most common case of a game mechanic that is hard to secure. Some basic things you should be doing in this scenario:

  1. Rate check the player, are they firing more often than their gun is able to?
  2. Do they have the ammo to fire?
  3. In terms of player position, I would do a comparison between the server’s position of the player and the communicated position and allow a small difference, over which the server position would instead be used.

Aside from this, you will have to trust the player’s arguments. Draw the ray server side, and communicate it to all other players in the server apart from the person who fired gun (you should draw the bullet’s path clientside for this player).

You always need to take performance into account, however. A system where the client who fired the gun drew the ray, and told the server what they hit would be much more performance effective, but would be much more easy to exploit. You as a developer need to choose a balance between security and performance.


#24

Dont have your exploit protection harshly punish the player like banning the player unless you’re 100% sure it’s not false positives.

If you have something like anti speed, simply reset the speed so not only does it help stop those speeding, but it wont penalize innocent players harshly


#25

Another thing which you can’t do is ever safely assume that a player can’t see the in the mechanics of your game. I’ve seen lots of tutorials online which assume that an exploiter can’t (for example) change a Boolean value in their character or something similar.

Also, for the idea on guns, many people store information about a gun’s stats in some kind of integer value in the gun. Ideally, you shouldn’t do this because an exploiter can simply change these values.

If you do use these values, just add server side sanity checks (I.E check if those stats were changed without permission) and you should be fine


#26

You as a developer need to choose a balance between security and performance.

I’ll definitely take that into account, didn’t really think about it like that until now. Thank you!