
UDP for games – encryption and DDoS protection - based2
http://ithare.com/udp-for-games-security-encryption-and-ddos-protection/
======
MichaelGG
>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
BTW, when I've wrote about those "undetected network errors", I've meant
those-network-errors-which-arise-in-UNENCRYPTED-packets (as 16-bit UDP
checksum is certainly not enough for this purpose). And DTLS etc. take care of
packet corruption themselves (actually, they consider it an attack).

~~~
astrobe_
The UDP checksum is twice unreliable since it's optional.

~~~
no-bugs
Since IPv6 it is mandatory, but it still sucks :-(

------
jzwinck
"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.

------
supernintendo
> ...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_Secur...](https://en.wikipedia.org/wiki/Datagram_Transport_Layer_Security)

~~~
zamalek
TCP and UDP occurring over the same route on a WAN can wreak havoc with UDP
packet loss.[1] Using both is only a good idea up until you dig deep into
socket performance. A network is not a piece of software where you can isolate
things and expect them to behave in an isolated way, everything you push over
it interacts with everything else that you are pushing over it. This "use UDP
and TCP" is a dangerous anti-pattern because it seems to be an obvious
solution from a software perspective, but is in reality a problem from the
electron perspective. To paraphrase a famous quote:

> Some game developers, when confronted with a TCP problem, think "I know,
> I'll add UDP." Now they have two problems.

Games that implement their own protocol over UDP typically have packet modes
(frequently a "channel" akin to WebSocket channels): reliable, ordered
delivery or neither or either. There is almost always the notion of a
connection, where appropriate. This is the correct way to do things, and with
Raknet now being free you really have no excuse to do it any other way.

For authentication you could just use the reliable/ordered channel and carry
on as though you were using TCP - which somewhat defeats the purpose of this
article.

[1]:
[https://www.isoc.org/inet97/proceedings/F3/F3_1.HTM](https://www.isoc.org/inet97/proceedings/F3/F3_1.HTM)

~~~
supernintendo
With my example for login, my assumption was that one would use short-lived
TCP connections (i.e. server receives login packet, sends success/fail and
finally closes the connection), not a simultaneous, persistent connection
where TCP congestion (and thus UDP packet loss) becomes an issue. But maybe
I'm wrong on this one.

Thanks for sharing by the way, great article (although as an aside, some of
those graphs are really hard to read).

~~~
zamalek
> some of those graphs are really hard to read

I have to admit that I had to squint a bit while reading it myself.

------
daurnimator
> 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
Last thing I've heard was that specifically CurveCP was separated from
libsodium into libchlorium, and it is not maintained now.

------
voltagex_
This 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.

~~~
AgentME
Here'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
How 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.

~~~
nindalf
Its not possible to maintain a rainbow table because the server would specify
the string to start with.

Server sends "randomstringthatalsoreferencescurrenttime"

Client needs to add strings to this such that the MD5 hash of the result has
the first N bits as 0 where N specifies the difficulty. The client is expected
to send what it added to the server's string and the server verifies the proof
of work.

~~~
AgentME
Oh, I left that out of my description. Having the server specify the salt or
the text required to be at the front of the value to be hashed does make
things better.

------
based2
[https://www.reddit.com/r/programming/comments/4gjjy0/udp_enc...](https://www.reddit.com/r/programming/comments/4gjjy0/udp_encryption_and_ddos_protection/)

------
chmike
Can someone please explain me as if I was 5 years old how the proof of work is
performed ?

~~~
grenoire
Like 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.

~~~
chmike
Sorry, 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.

~~~
dividuum
The 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.

~~~
hefty
Maybe I'm taking your example a bit far, but it seems like you'd have to
choose the hashing function carefully, correct?

To use your example, it must be 100% certain that a hash with 6 leading zeros
is possible to generate with md5.

Also, I'm assuming you don't want clients spending too long on the problem, so
it seems like you'd want to have a prediction of roughly how long it would
take to compute the answer. Otherwise one client may get lucky after 10
iterations whist another may take 10 million. Are hashing functions
predictable in that manner?

~~~
grenoire
Reliable hash functions must be able to map to all combinations of 256, 512,
or however many bits they are using.

------
zond
If 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
Good 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".

------
eps
> 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
You're right, I forgot about it. But is there a ready-to-use library doing it?

------
Thaxll
On 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 )

------
asdfadr1344kk
Yes, 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
The 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.

------
sleepychu
Doing a lot of crypto at work so this article was super interesting. My god
though, those illustrations are gorgeous.

