2
\$\begingroup\$

I'm working on a Unity project with the Lidgren UDP library for connection. I'm new to networking, so I'm not sure on general "best practices" for this area. I'm trying to figure out a good way to be able to quickly trust and verify a received UDP message.

I currently keep a dictionary of players with each player assigned an UID (uint) from the server when the player connects. This UID serves as the key in the dictionary. The player is told their UID. Nothing secret being communicated here, like usernames/passwords, so I'm not worried about things like that.

So I'm having a problem with wrapping my head around how to trust the messages. Things like position updates and user actions will be sent from client->server via UDP. I was thinking of a quick way to process these messages is by including the UID at the start of each message, checking the UID, grabbing the corresponding player from the dictionary, and then updating the players position that way.

But I'm worried that can be easily spoofed/manipulated. All it'd take is some mischief maker to figure it out, and then start inserting random position updates (for themselves or others).

Is there an efficient, more fool proof way to ensure the message is from who it claims to be? Do I have to just rely on comparing IPEndPoints to tell? Is there anything specifically to Lidgren I can or should use?

Please don't respond if all you have is "don't worry about it" or "why would anyone want to do this?" I'd rather learn proper processes now than down the road when/if it becomes a problem.

\$\endgroup\$
  • \$\begingroup\$ The concept you're looking for is 'authoritative server,' and has been asked about many times before on this site. \$\endgroup\$ – BlueRaja - Danny Pflughoeft Feb 21 '14 at 22:22
  • 1
    \$\begingroup\$ I'm familiar with the concept. But that's not the question I'm asking. I'm not asking how to to prevent players from attempting to cheat at the logical level (via teleporting). I'm asking how to trust the message is from whom it claims to be. Don't care about the message contents implication at this time, just validating the source. \$\endgroup\$ – user42524 Feb 21 '14 at 22:31
3
\$\begingroup\$

always double check on the server, don't allow teleportation through position but instead ensure the speed isn't too large

you can ensure authenticity by having the client keep a counter and encrypt it together with UID with a prearranged client-specific secret (also send the unencrypted counter to account for lost packets)

\$\endgroup\$
  • \$\begingroup\$ Ah! This will do nicely. Thank you. How do I handle resyncing the counter? Server just needs to send a "correction notice"? \$\endgroup\$ – user42524 Feb 21 '14 at 22:43
  • \$\begingroup\$ no just have the server verify, against the sent counter. that's why I said to also send the unencrypted counter \$\endgroup\$ – ratchet freak Feb 21 '14 at 22:51
  • \$\begingroup\$ technically you don't even need encryption just a salted hash of the counter with the salt being the preshared secret \$\endgroup\$ – ratchet freak Feb 22 '14 at 1:05
2
\$\begingroup\$

Remember that Lidgren sends messages that are assigned 'MessageTypes'. One of those MessageTypes is a StatusChanged (Connecting, Connected, Disconnected, etc)

Lidgren assigns each new connection with a unique remote identifier. If you couple that with packet encryption that is available via the Lidgren framework then that should be sufficient.

Client connects to the server, server verifies the connection and assigns that client a unique remote identifier (this is handled by Lidgren, and the identifier can be accessed on any incoming message that is read with server.ReadMessage() by accessing it as follows:

NetIncomingMessage msg = server.ReadMessage();
string uniqueID = NetUtility.ToHexString(msg.SenderConnection.RemoteUniqueIdentifier); // as shown in the examples provided by Lidgren.

Once the client has made a connection to your server, you may send a 'sharedkey' from the server to the client (you may wish to encrypt this message with a key that every client shares locally, just so it's not transmitted in 'plaintext')

Once the client knows the sharedkey, you can then begin encrypting your messages from the client/server and decrypting them at either end using that sharedkey.

\$\endgroup\$
0
\$\begingroup\$

Calling Network.InitializeSecurity() prior to initializing the server is supposed to prevent this sort of attack.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.