PlayerPing - Get client ping times on the Server

I guess the issue is with your ISP, not my module :laughing:

Thanks for reporting though, I appreciate the thought. Better safe than sorry!

1 Like

Ok, sorry if I might be sound dumb, but how it works? I can‘t understand what berezaa said and if you are using the same method or not.

(P.S.: Yes, this sound really dumb, sorry for this question)

Sure, I’m happy that you asked. Here to help.

Essentially, the server invokes the client and measures how long it takes to respond. To make sure that the client response isn’t being faked/manipulated/corrupted, the server sends along a random piece of data with the request and the client must send that data back. If they don’t send back that exact data, we know that some funny business is going on and disregard the request.

(PS: It’s never dumb to ask a question! It would be silly to need to know something but never ask or learn!)

11 Likes

Wow, thanks for helping!

This sound really good. I am asking if it is possible to applicate this security system to other thing (Code verification, idk system like this)

Can this essentially detect that an exploit is happening to which our code can carry out the kick script?

If you think you’re question is dumb, ask it anyways! It’ll allow you teach yourself new information!

Nope! That would be a bad plan. A player with a poor connection might be kicked unfairly because of corrupted data, packet loss, or any number of weird things. Networks aren’t magical, so we can’t rely on them being perfect!

1 Like

This system is designed to validate responses. If you can think of another use case, great! But it’s not made to confirm that something has “worked”.

1 Like

But with this line you’ve stated, can I still detect whether it’s being exploited?

Sorry if I missed something, but what does it say the ping is when it times out? Does it do the 100 ms for that (even though it’s probably higher than that)?

2 Likes

Perhaps I should have chosen my words more carefully. Funny business could mean that their network is screwing up!

3 Likes

Ahhhh thank you for the clarification! I thought when you said “funny business” you meant exploiting, sorry about that! Thank you for creating this, I’ll take a look at it and hopefully implement it into my future game!

1 Like

If it times out, it discards that request attempt. If the ping request was successful before, it’ll remain at that value. If it was never successful, it stays at the default value.

2 Likes

Oh, so this is how the developers of New User Machine get everyone’s ping time and show it over their nametag.

How does making the client return a GUID prevent exploiters from spoofing it? Is there some reason why exploiters can’t just return the GUID passed by the remote function?

It prevents pre-emptive spoofing, since they can’t know the GUID ahead of time. Therefore, they cannot lower their ping. However, they can artificially raise their ping, unfortunately. There really isn’t a good way to prevent this. How can you distinguish an intentionally bad ping from a real bad ping? To the server, they’re identical.

3 Likes

This is a pretty nice module but, I have a few critiques, wouldn’t an exploiter want to increase their ping instead of make it seem really low as I don’t really see much use of faking your ping so it seems lower than what it actually is; on the other hand, increasing their ping would allow them to “trick” lag compensation on a server to register a hit allowing them to shoot players who aren’t in sight (one example).

Ping can be easily increased by an exploiter, one way this could be done is by hooking functions so Remote:Fire(...) will yield for a short amount of time before firing (there’s an example below); using a key will probably prevent most exploiters (script kiddies) but, some exploiters will be able to easily get around. Arguments passed through Remote:Fire(...) will be passed to the hooked function which an exploiter can pass through the original function used to fire remotes, rendering the use of keys useless in most cases.

I’ve considered a few alternatives such as using a players position to determine what their ping is but, if a player is stationary, their ping will seem really high. A part that a player has network ownership could be used but, if an exploiter finds out, it might be even easier for them to fake their “ping”.

local FireServer
FireServer = hookfunction(Instance.new("RemoteEvent").FireServer, newcclosure(function(Event, ...)
    if not checkcaller() then
        if Event == [some event] then
            wait(n)
        end
    end

    return FireServer(Event, ...)
end))
-- Hookfunction: allows you to hook functions
-- newcclosure: prevents some (if not, all) current detection methods (e.g. environment checks)
-- Checkcaller: checks if a Remote was fired by a game script (if so, it'll return false)

Thanks for sharing this module though, I’m sure it’ll have really nice use cases :+1:

3 Likes

Sending os.clock() instead of GUID would be enough and you would also receive a synced up server time reference on the client. os.clock() is a floating point value and guessing the right one for exploiters would be very tedious already.

8 Likes

Awesome module! Thank you!

Accurately grabbing ping of players was always something I would find hard to write myself <3

I was looking into Postie and discovered a major issue with how old listeners are cleaned up. Essentially, if multiple requests are sent around the same time (as they would be with a system like PlayerPing) and are not returned in the correct order, requests can be “lost”. I have described the issue in detail in the reply linked below as well as uploaded a modified version of Postie that addresses the problem. I’d recommend you to either use that or come up with your own solution.

2 Likes

cant exploit just decompile your script and copy and then disable yours and make there script return what ever they need and the value the server send