Secure Yet Accurate Gun Raycasting?

How can I create a secure yet also accurate method of detecting hits in a shooter game?

Server Raycasting - Secure, but poor latency on Roblox results in clients hitting enemies on their screen, but not on the server.

Client Raycasting(Client tells server when they hit someone) - Very easy to exploit, but keeps hits consistent on the client and the server.

How can the server validate the legitimacy of client side raycasting?

3 Likes

This has nothing to do with the post. FastCast is just raycasting but it emulates a projectile. The OP is asking about just raycasting.

To the OP, you can look into how Valve does lag compensation. Fair warning, it is a pretty hefty document.

9 Likes

But it’s not possible to achieve the Valve client-server model on Roblox unless you create custom character control scripts.

oooh I’m tryin’

https://developer.valvesoftware.com/wiki/Lag_compensation

That is a different kind of lag compensation. You still seem to depend on client data in order to detect hits which will not really help if the player is teleporting around the map.

This is a problem I tackled in my shooter. I employed a bunch of different methods to try to minimize the amount people can cheat through the gun system. The main problem is the client needs to be given a lot of control for shooting in a FPS, or you’ll run into ugly response times.

  1. One of the main ways I check for this is through a cone-of-fire check.
    I keep track of where the player is looking (a vector direction value). Whenever they shoot the gun, and the server receives their shoot request, it will run a cone-test, to see if they are requesting to shoot in the direction (within a MOE [the cone]) the server sees them. If you are shooting at a player that is outside of your cone, your request is ignored. Since the cone is server-sided, it helps to work against people that teleport other players to them to shoot. The server will see them at their original position, and fail the test.

  2. I also have an asynchronous key system set up, so when I want to damage a player I must use the public key and encrypt their name with the key. On the server it uses the private key to decrypt the name, and if it matches the player you are trying to damage, you pass. That result is also sent to the server. This helps against a lot of common cheats where people will exploit to try to damage all players in the server. It’s still by-passable if you try hard enough, but it helps against script kiddies.

  3. I limit the amount of players the player can request to damage at a given time. If you send too many requests to damage different players too quickly, your damage requests are ignored. (this is also a helpful counter for problem 2)

  4. I have a server-sided anti-noclip script that I wrote. If players try to delete parts locally and walk through them, the server will teleport them back. If they continue to try to walk through it, it’ll kill their player

  5. When a player shoots an object, the client is forced to send the size of that object to the server as well. If the sizes do not match, the clients request to shoot is ignored. This is useful to stop “big head” exploits, where exploiters will make the head size of other players large so that you can shoot them easier. This also works with the cone-of-fire check (Problem 1). If a user makes another users head large, and shoots it, it’s possible that they will not pass the cone-of-fire test, and their bullets will be ignored as well.

  6. I have multiple remote events required to shoot. I have one that is fired when you wish to shoot, and I have another that is fired when you wish to damage a player. Both of these remote events run different tests (listed above), and if you fail any one of them, you fail both the events. I wanted to use two different remotes, so that it was slightly harder for exploiters to send fake remotes. You cannot send a damage request without first sending a shoot request. It’s by-passable, sure, but it makes it more complex for the exploiter.

I guess the common theme is to try to make things more obscure. Someone that really wants to try to exploit your game probably will, with enough time. But what I’ve written is good enough for common script kiddies trying to do anything.

6 Likes

These tips are really useful! I’ll definitely try some of these. Can you give me a bit more info on how the encryption work or link me to an article?

  • When the server starts I use an RSA method to generate a public and private key.

  • When a client connects to the server, I create a String value in their player containing the key (Because most exploiters listen for remote events, I didn’t want to use a remote event). I delete it a few seconds later, after I’m sure the client has connected fully (and has had the ability to read it).

  • The gun script also has access to the RSA module, and uses it with the public key to encrypt the players name when shooting.

  • The same RSA module is used with the private key to decrypt the encrypted text on the server’s side.

You can google something like “lua rsa implementation” to find a good implementation.

You don’t have to use RSA encryption though. You could use simpler things. I googled and found this just now:

4 Likes

I dont see how that would help too much as an exploiter could also check what people are sending into the remote event.

2 Likes

Encrypting your remotes is stupid and doesn’t stop any hacker that knows what they’re doing, and it only takes 1 hacker who’s dealt with it a million times to write and release a hack, and then the entire system breaks. RSA prevents MITM, not if the attacker has direct access to the client itself.

4 Likes

I never said otherwise.

Why I chose this as one of my many methods to stop exploiters (key word, many methods!), is another layer of obscurity. The point of this is I mix the name of the user that is being shot into the encryption, sort of like an initialization vector. So each player being shot would have a different value being sent to the server. Sure, with enough time, someone could figure it out, but they also have many other trials they must overcome.

To simply brush it off as useless is ignorant. All security is, is obscurity.

After a year, and 6 million plays on my game, I can say that it works quite well. I’ve had a lot of people try to write exploits for my game.

1 Like

Wait what
Security through obscurity is literally the worst security and that’s like the first thing you’re told when making things secure.

Your system is incredibly weak and isn’t going to keep holding up. Any sort of encryption will never work because clients can see how it’s done when they decompile or look at modulescripts.

2 Likes

You’re just… wrong.
My system isn’t weak. Like I’ve said, there are many components to the security of my game; encryption is just one of them.

1 Like

No there wouldn’t be. Find where guns fire, hook there, skip the whole RSA stuff.

…No?

Then do it. Write exploits for my game. Prove me wrong.

1 Like

this is the difference between a constructive proof and an existential proof; a constructive proof would be to actually create an exploit for your game, whereas an existential proof, which has been provided, simply proves the existence of a vulnerability that would enable such an exploit.

your game cannot be truly secure if it depends on the client behaving how you want it to. if you put things on somebody else’s computer then they can change it and you can’t stop them.

your aim, though, is obfuscation, and that isn’t necessarily accomplished either because the client has the potential to simply run different inputs directly through your existing remote security code without needing to understand how any of it works.

1 Like

Obviously. But I feel this is borderline pedantic. Fundamentally in a first person shooter, a lot of trust has to be given to the client in the name of response time. Other game-types do not suffer from this problem, as they do not require this. See RTS’s, MMO’s. OP highlighted this in his own post.

No first person shooter can be truly secure. Especially when the only tools we have are working at such a high-level (lua). Triple A game companies still see these issues, and they’re able to write programs with a much broader range of complexity and at a much lower level. See Valve’s VAC or BattlEye; They are both by-passable.

All of the suggestions I’ve given slow exploiters down. I’ve yet to see anyone else offer anything useful to the OP other than “No don’t do that it’s worthless”.

2 Likes

Is there not existential proof that any and all security algorithms won’t someday be broken? The point here is that we try to secure something. There is no perfect, permanent solution to any problem relating to security.

As orange points out, there is very little hope in truly securing any game that requires any input from a client. This is an age old problem. This is why third party applications exist that monitor your activity as you play a game. Maybe his methods aren’t perfect but they’re at least an attempt at something secure. Ideally he would be able to watch player’s processes but that’s not an option. This is unproductive to argue like this and it does not help OP.

A better, more productive, approach would be to expand on oranges answer. Unless you have a better idea but in that case you should post it.

1 Like

Clearly, shooter genres are very limited in network security and the only two ways to deter hackers are:

  1. Run sanity checks on the server(cone of fire, dmg per second, ammo count, etc)
  2. Muddle the scripts as much as possible through encryption

While neither of these methods are completely secure, they slow down the more advanced hackers and probably completely stops the script kiddies and that’s really all I’m looking for given the futility of fully securing a shooter game.

Thank you @orange451 for offering your methods. Sorry this turned into an argument :woman_facepalming:

6 Likes

You can also do what Rocket League and a couple of other games do where input is replicated and clients just follow with prediction methods, not actually setting their own location on server.