7 ms·
UDP for games – encryption and DDoS protection
- chmike 11y agoCan someone please explain me as if I was 5 years old how the proof of work is performed ?
- grenoire 11y agoLike Bitcoin, you can ask clients to find a hash of a string (in the format of, say, 'server_key' + 'random_number' + 'client_adjusted_nonce') with the value of the last four bytes being higher than say 50,000. You can increase the value until 0xFFFFFFFE, where only 1 in 4294967296 hashes would 'pass' the test. Your client will basically be working on passing the test for a predictable amount of time, dependent on the difficulty threshold. The neat thing about this method is that although it takes a while to pass the test, it's very fast and easy to check if a test is passed. You'll simply ask the client for the client_adjusted_nonce which gets a value higher than 50,000 (or whatever difficulty threshold you choose). As the author has stated, you can adjust the threshold depending on the strength of the DDOS.
- dividuum 11y agoI remember first seeing such a proof-of-work in the network protocol layer of the game Tribes 2. They opened up the source code for that, named OpenTNL (seems abandoned now) where you could see how it's done. Here's the part that verifies a puzzle: https://github.com/kocubinski/opentnl/blob/master/tnl/clientPuzzle.cpp#L107 https://github.com/kocubinski/opentnl/blob/master/tnl/client...
- deleted 11y ago[deleted]
- chmike 11y agoSorry, my age may be lower than five. I don't understand. You explain that a hash is computed over a string that is the concatenation of a server key, a random number and a client adjusted nonce. you then lost me with the four bytes. I thought that we were talking about a string of chars, not an array of bytes. The nonce is an integer value ? The client then increases the nonce value I guess. But how does the client know it has finished the work ? In the article it is said that the hash value should start with a number of 0 bits. But this occurence is random by definition of the hash. It could never occur with the nonce tested. So sorry, I still don't understand it.
- zamalek 11y ago> The nonce is an integer value? An array of bytes is an integer value - just an arbitrarily large one. You could also just tack the bytes of a 64-bit uint onto the end of the nonce instead of incrementing the nonce (I'm not sure if that is secure, it's just an explanation). A real example of this is RSA. The length of the key is in bits (and therefore bytes) but is still a representation of a really big integer. > how does the client know it has finished the work ? Let's remove hashing from the equation. I, as the server, say to you I've got the following equation: Y = (5 + X) * 10 Please solve it so that the last 3 digits of Y are greater than 100 and tell me what you used for X. The simplicity of this equation means that you can easily solve for Y and respond with `12335`. With that response I can just plug X into the equation and see that you've done the work. Now, imagine that there is no such thing as division. Being unable to solve the equation, you'd be forced to brute force each value of X - but proving that you've found X only requires that you run the equation once because we can still multiply: Y = (5 + 12335) * 10 With POW, you say that you are looking for a specific pattern of bits or bytes. The pattern can be quite arbitrary: "I want the last 8 bytes to be a 64-bit integer larger than 12345" or even just "the last 64 bits must all be 0." The client will have to try multiple values of X to see which satisfies that constraint. Once the client knows X you no longer need to go through the effort of finding out the value for yourself, you just need to plug X into the equation and see that they found a valid value for X: POW = HASH(NONCE & X) It's like salting a password, but requiring that a portion of the final result has a specific pattern. This forces the client to do a lot of work in a way that is cheap to verify from a computational standpoint.
- dividuum 11y agoThe basic idea is: The client has to create a hash that satisfies a certain condition: Like the first n-digits must be 0, or maybe "the last bytes (when interpreted as a single 32 number) must be larger than x". So the client does this: from itertools import count import hashlib for i in count(): h = hashlib.md5("some-nonce:%d" % i).hexdigest() if h.startswith("000000"): print i break The value "some-nonce" is provided by the server. It also provides the difficulty by saying: I need you to find i which generates a hash that starts with 6 zeros. So the client calculates hashes for a while, and then submits the value 2652076 to the server. The server can the trivially check if the client did its work correctly: $ echo -en "some-nonce:2652076" | md5sum 00000066adb2fb37a8460da553721c39 # ok, the first 6 digits are 0 The server can simply increase the difficulty by requiring the client to return more leading zeros. Or, if it should be more finegrained, a value below a certain threshold.
- based2 11y agohttps://www.reddit.com/r/programming/comments/4gjjy0/udp_encryption_and_ddos_protection/ https://www.reddit.com/r/programming/comments/4gjjy0/udp_enc...
- Thaxll 11y agoOn the end encryption is useless but it blocks 90% of the curious people that don't have the skills to go further ( ie: reverse engineer the game )
- jzwinck 11y ago"encryption is to prevent eavesdropping and session hijacks by the third party [...] it is Really Important for stock exchanges" Stock (and other financial) exchanges are major users of UDP, but in general they do not encrypt it. Exchanges give clients direct connections to their networks using dedicated Ethernet lines, one per customer. This, combined with datacenter security, is what prevents eavesdropping and session hijacking. They do not use UDP over the Internet at all.
- MichaelGG 11y ago>As a side bonus, with proper encryption you can be sure that network errors which corrupt your packets are not going undetected Shouldn't you be verifying a MAC before decrypting anyways? Relying on decrypting scrambled data, especially for a bitflip, seems like a bad idea. >Potential attack here is about attacker modifying the (unencrypted/unsigned) data coming to the victim’s Client, So establish a session key, and include an HMAC on each message? Or not even a session key, if you're worried about re-establishing sessions, but a long-term per-client key (or per-install or whatever). Hardly seems like you need QUIC/DTLS for this simple scenario. Then all the part about DDoS'ing a UDP connection establishment... Why not just use TCP for sign-in and key establishment, and get 3-way handshake for free. That eliminates spoofing IPs. From there, just have monitors that determine when you're "under attack" and rate limit by IP address, just like any anti-DDoS does. Coming up with all this other stuff seems like an overly complex way.
- no-bugs 11y ago> Shouldn't you be verifying a MAC before decrypting anyways? Relying on decrypting scrambled data, especially for a bitflip, seems like a bad idea. Oh, we're going into the realm of MAC-then-encrypt vs Encrypt-then-MAC, which is waaaay out of scope of this book. As it's mentioned in some footnote, under "encryption" I've meant "the whole package, including encryption, integrity authentication, etc." (which is currently routinely done by some kind of AEAD for wired data). I certainly don't want to go into a deep crypto-level discussion of AEAD etc. in a book for app-level developers; what I'm aiming for here, is a simple recipe of "just do it this way, it will work". > Why not just use TCP for sign-in and key establishment, and get 3-way handshake for free. That eliminates spoofing IPs. From there, just have monitors that determine when you're "under attack" and rate limit by IP address, just like any anti-DDoS does. But then, for UDP (and you DO need UDP for fast-paced games) you will need your own protected protocol (probably using keys exchanged over TLS-over-TCP). There are many ways to do your own protocol wrong, and only a few to do it right; and if an average app-level developer will try doing it - it is much more often a disaster than not :-(. As a result, I am arguing for using standard security protocols wherever possible (and the anti-DDoS hack described there keeps DTLS security intact, this IS important).
- 11y ago
- voltagex_ 11y agoThis talks about a "proof of work" system to mitigate DDoS. What's the "hello world" of such a system look like? It came up in a CTF recently and I had no idea where to start.
- jevinskie 11y agoThis is some old code, based off of the hashcash algorithm, that prototypes protecting DNS servers using a proof of work (also UDP). https://github.com/jevinskie/SlothNS/blob/master/pow/pow.c#L58-L116 https://github.com/jevinskie/SlothNS/blob/master/pow/pow.c#L...
- voltagex_ 11y agoMaybe I'm misunderstanding things - is this a particular algorithm (that I could look up in a textbook for example?)
- jevinskie 11y agoAfter looking into it more, I think the implementation is more Coelho et al than hashcash. Sorry, this was long ago for me. http://www.cri.ensmp.fr/classement/doc/A-370-v2.pdf http://www.cri.ensmp.fr/classement/doc/A-370-v2.pdf
- AgentME 11y agoHere's a really simple proof of work system: during connection, the server tells the client some randomly generated bytes and a number of bits, and then the client has to come up with a string whose MD5 hash (or whatever algorithm you want to use) has its first N bits match the first N bits of the bytestring that the server gave. It's easy for the server to adjust the difficulty of the proof-of-work: it just needs to given a larger bitcount to force the client to match a longer prefix.
- chmike 11y agoHow is the client expected to proceed ? Should it try a,b, ... aa, ab, ... ? Couldn't a rainbow table allow to cheat with such algorithm ? It seam that the computation of a MAC or an encryption where the key serves as salt could prevent such cheating. But this computations are now hardcoded in the cpu which won't be the same proof of work for everybody.
- daurnimator 11y ago> Both known-to-me implementations of CurveCP (NaCl and libchlorium) seem to be pretty much abandoned as of beginning of 2016, libsodium (the continuation of NaCl) is actively maintained.
- no-bugs 11y agoLast thing I've heard was that specifically CurveCP was separated from libsodium into libchlorium, and it is not maintained now.
- deleted 11y ago[deleted]
- supernintendo 11y ago> ...if some artifact within your game costs $20K+ of real-world dollars – you should start thinking about [encryption] seriously. In these cases, game account becomes as important as (and for quite a few people out there – much more important than) a bank account. Which carries all the security implications of the bank, including (but not limited to) encryption. Sorry to nitpick but UDP seems like the wrong protocol for authentication. TCP is connection oriented. It's a better choice for logging in, refreshing a server list or any transaction where reliability is more important than latency. Most online multiplayer games use both TCP and UDP for this reason. As for encryption, of course you should always use it when transmitting sensitive data. For a game where the client has no control over the state of the world and all packets are at the discretion of the server (`move here`, `click that`, etc.), encryption might be overkill. The source port value (first 16 bits of a UDP packet) can be used to identify the source of a packet and associate it with a client's server side session. But I'm not saying that encryption is a bad idea (it never is); it just depends on how much you can afford. [1] https://en.wikipedia.org/wiki/Datagram_Transport_Layer_Security https://en.wikipedia.org/wiki/Datagram_Transport_Layer_Secur...
- ComputerGuru 11y agoI don't understand - DTLS is covered in depth in the article (as are your or concerns)
- MichaelGG 11y agoI took it to mean that you might use UDP for doing stuff in game that might result in losing items. Like, I dunno, maybe an attacker on campus or on WiFi proxies your connection then makes you lose or drop expensive items. I'm not sure how realistic a threat this is. Most likely crypto just helps obfuscate the game to make cheating/RE a bit harder.
- c22 11y agoWhen I used to play games like this the popular technique was to dos your connection, then just kill you and take your stuff while you're trying to reconnect.
- eps 11y ago> DTLS and QUIC And, of course, the mother of all datagram encryption protocols - the IPsec suite (ESP, IKE 2). It works with IP packets, but it can be very easily repurposed for UDP.
- no-bugs 11y agoYou're right, I forgot about it. But is there a ready-to-use library doing it?
- zond 11y agoIf you encode each packet in a QUIC stream with it's own stream ID, and close QUIC streams after a timeout, you can use QUIC for unreliable unordered transports as well.
- ithare 11y agoGood idea, THANKS A LOT! It has crossed my mind too, but I've discarded without giving it enough thought. The reason why it MIGHT work, is because of the implicit stream creation in QUIC (no handshake, nothing, just single UDP packet). There will still be some overhead, but probably it won't be "too bad".
- sleepychu 11y agoDoing a lot of crypto at work so this article was super interesting. My god though, those illustrations are gorgeous.
- asdfadr1344kk 11y agoYes, use DTLS, the protocol that is not a bastard stepchild of TLS and NEVER gets blasted open by protocol-level security holes, and certainly never by implementation flaws. Yes, use that.
- llama9000 11y agoThe more I look at this website, the more I think they should go write a children's book on coding. That being said, pretty good read.