|
|
# QUIC
|
|
|
|
|
|
Google's QUIC is a very interesting and recent protocol. You can find its code in chromium, there's no external library...
|
|
|
|
|
|
You can find some of its features summarized [here](http://www.riskcompletefailure.com/2013/08/quic-notes-stream-multiplexing-and.html) and [here](http://www.riskcompletefailure.com/2013/07/quic-notes-rational-fec-and-head-of.html)
|
|
|
|
|
|
There is also an introductory video (nothing advanced ~51m) on [youtube](http://www.youtube.com/watch?v=hQZ-0mXFmk8)
|
|
|
|
|
|
The main document that lists its features and design rationale is on [google docs](https://docs.google.com/a/google.com/document/d/1RNHkx_VvKWyWg6Lr8SZ-saqsQx7rFV-ev2jRFUoVD34/preview?sle=true&pli=1) , there's a [crypto document](https://docs.google.com/document/d/1g5nIXAIkN_Y-7XJW5K45IblHd_L2f5LTaDUDwvZ5L6g/view) and there is also a [wire layout specification](https://docs.google.com/document/d/1WJvyZflAO2pq77yOLbp9NsGjC1CHetAXV8I0fQe-B_U/view) you can read
|
|
|
|
|
|
Here we will look at the main differences between QUIC and Fenrir
|
|
|
|
|
|
----
|
|
|
|
|
|
## General:
|
|
|
|
|
|
I still have not understood if QUIC supports unreliable connections or not. If it doesn't it probably is a silly limitation, as the design seems to allow it, so I'll assume it does, although I'm not sure.
|
|
|
|
|
|
The main selling point of QUIC is that it redces latency and messages needed to setup the connection or to manage it.
|
|
|
|
|
|
This is true, as compared to TCP QUIC does a lot more work with much less overhead. TCP also has the well known [slow start](http://en.wikipedia.org/wiki/Slow-start problem).
|
|
|
|
|
|
There are TCP options that we can use to avoid this problem, but they make the TCP header bigger and are not a requirement for the implementation.
|
|
|
|
|
|
Fenrir Tries to do the same as QUIC in regard to the number of packets required to manage a session, but extends the same concept to encryption and authentication.
|
|
|
|
|
|
### packet size
|
|
|
|
|
|
By having integrated encryption and authentication we don't need redundant identifiers for the connection, and can optimize the packet structure as a whole.
|
|
|
|
|
|
The result is that you can send encrypted and authenticated messages with Fenrir in just about 28 bytes. QUIC can take up to 45 bytes, and that's assuming that there is no TLS overhead (which usually uses a 18-byte header)
|
|
|
|
|
|
### RTT needed
|
|
|
|
|
|
The connection setup is a 4-way handshake with cookies to avoid SYN flood attacks, much like SCTP. Fenrir uses a similar structure.
|
|
|
|
|
|
QUIC supports a 0-RTT reconnection. As long as the connection doesn't time out for too long, Fenrir does the same.
|
|
|
|
|
|
This is because both QUIC and Fenrir use a id for the connection. This also means that both protocols have automatically enabled multi-homing features and support mobile devices.
|
|
|
|
|
|
Fenrir is actually a federated authentication protocol, so things are a little more complex, and the first time we authenticate into a federated server we might actually get up to 4 RTTs. 3 RTTs are the norm after the client has its authentication data signed for its domain.
|
|
|
|
|
|
## Perfect forward secrecy
|
|
|
|
|
|
PFS is mandatory in both Fenrir and QUIC. The only difference is that Fenrir keeps the single connection safe from the others, while QUIC changes the ephemeral public key every once in a while, so more authentications are done with the same public key.
|
|
|
|
|
|
This enables QUIC to have one RTT less then Fenrir, but the connection is not totally isolated.
|
|
|
|
|
|
As long as the ephemeral public key is changed quickly (let's say, every couple of minutes at most) this seems a good idea, and Fenrir **might** implement it.
|
|
|
|
|
|
### PFS on resumed connections
|
|
|
|
|
|
QUIC simply tries to guess that the last public key used is still in use, so it hopes for a 0-RTT reconnection, and has a fallback to 1-RTT reconnection.
|
|
|
|
|
|
In Fenrir I will implement an additional public key exchange, which will take place during the data transmission, so that the client and server have an agreement for reconnection that respects PFS and doesn't depend on the ephemeral key being the same.
|
|
|
|
|
|
## Forward Error Correction
|
|
|
|
|
|
This is a nice improvement of QUIC over previous protocols:
|
|
|
|
|
|
basically every 4 packets we send an other packet which is the XOR of the previous 4. So if one was lost, the receiver can reconstruct it without asking a retransmission.
|
|
|
|
|
|
This is actually a good idea, and I decided to copy it and put it into Fenrir. Since it might take some time do so, since I've just started coding Fenrir, I will also experiment with other methods of FEC and do some simulation to get the most out of this idea.
|
|
|
|
|
|
## Stream/connection identifiers
|
|
|
|
|
|
Both QUIC and Fenrir have a variable number of streams to be used in a connection, and both use a 32-bit connection identifier at the beginning of the packet.
|
|
|
|
|
|
QUIC stream identifiers are actually larger (32 bits) then Fenrir's (16 bits), but really, todays applications use just one stream (TCP) for everything, 65534 streams should be enough...
|
|
|
|
|
|
QUIC uses a 64-bit sequence number for its streams, while Fenrir usually has a 24-bit one, like TCP. Having a bigger sequence number is actually a good thing, as it helps a lot in low-latency -high bandwidth connections, such as satellite ones, but 24 bit should be enough for everybody (and 64k of ram, too...)
|
|
|
|
|
|
### Limitations?
|
|
|
|
|
|
This has some limitations, however. It means that if we use a 24-bit offset we can't send more than 16Mb of data without an acknowledgment.
|
|
|
|
|
|
16Mb should be enough, as it means that the sender has to saturate a 1Gbit connection while the receiver can not send even one packet per second. As this situation seems a little extreme, I don't think it makes much sense to support it.
|
|
|
|
|
|
Does this means that the maximum message size will be 2^24 = 16Mb ? Not really. That is the maximum window size. But as soon as we have the initial part of the message complete, we can put it into a buffer, and wait for the rest, and we can keep doing this as many times as we want.
|
|
|
|
|
|
Of course, you should not expect Fenrir to handle a multi-Gb buffer. The packet will be truncated at a certain length (user defined) and a partial message will be delivered to the user application. Big messages are usually just file transfer anyway, so chunking them does not give any problem. And do you really want Fenrir to keep a 2^64 buffer?
|
|
|
|
|
|
## Proof of ownership
|
|
|
|
|
|
This means that we want to be sure that the one who sent the packet is the one we think he is, and not someone else.
|
|
|
|
|
|
Aside from the authentication header, QUIC uses the usual RTT method to be sure, but also an other peculiar method: it makes a specific bit in the stream field random, and the two endpoints continually exchange the hash of these random bits. Which means that they have problems when a packet is dropped or lost.
|
|
|
|
|
|
Fenrir uses only an authentication header, and makes sure that at least one RTT has been done before "trusting" an ip address. The auth.header structure varies from algorithm to algorithm, but its purpose is to make sure that the sender is not a fake. Not much more cryptography is involved, and we don't fear retransmissions/packet loss anymore.
|
|
|
|
|
|
## ACKs
|
|
|
|
|
|
Every protocol that wants to provide reliability has to include some form of acknowledgment (ACK).
|
|
|
|
|
|
In QUIC ACKs are the same as in TCP. The whole packet is ACK'd, using the packet sequence number.
|
|
|
|
|
|
The SCTP and Fenrir way of doing ACKs is not only to acknowledge the last stream offset, but to send acknowledgments also for incomplete chunks.
|
|
|
|
|
|
So if we received the bytes 1...10 15...30 of a message, maybe because the 10..15 bytes were lost, we acknowledge both the 1...10 and 15...30 chunks in a single message. This should help the sender to retransmit only the part that we want, so in case of retransmission we should have a lot less duplicate packets
|
|
|
|
|
|
## Congestion Control
|
|
|
|
|
|
Quick uses the TCP-Cubic algorithm, the same used by linux today. It can also track the time of each packet with timers.
|
|
|
|
|
|
I haven't decided exactly what to use yet, but I think I'll be going for the [curvecp congestion control](http://curvecp.org/decongestion.html) algorithm, as it tracks both bandwidth and RTT estimations.
|
|
|
|
|
|
I will be doing some simulations before deciding the final algorithm, but the idea is to track packet loss, RTT and trying to get as close as possible to the maximum without dropping the transmission rate too much once we reach a congestion or have a packet loss (see [TCP behavior](http://c3lab.poliba.it/images/5/5a/Tcp_westwood.gif) ) |