|
|
# QUIC
|
|
|
|
|
|
Google's QUIC is a very interesting and recent protocol. You can find its code in chromium, there's no external library...
|
|
|
Google's QUIC is a very interesting and recent protocol. You can find its code in chromium, and there are multiple implementations around even though it is not yet stable
|
|
|
|
|
|
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), and there's the [RFC](https://datatracker.ietf.org/doc/draft-ietf-quic-transport/)
|
|
|
The Draft seems to be tracked [via github](https://github.com/quicwg/base-drafts)
|
|
|
|
|
|
There is also an introductory video (nothing advanced ~51m) on [youtube](http://www.youtube.com/watch?v=hQZ-0mXFmk8)
|
|
|
|
|
|
A lot of documents are pooled [here](https://www.chromium.org/quic).
|
|
|
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
|
|
|
A 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
|
|
|
|
|
|
Some of the above could be outdated, use the github repository for the latest up-to-date standard.
|
|
|
|
|
|
Here we will look at the main differences between QUIC and Fenrir
|
|
|
|
... | ... | @@ -21,7 +24,7 @@ This is true, as compared to TCP+TLS QUIC does a lot more work with much less ov |
|
|
|
|
|
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.
|
|
|
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.
|
|
|
|
|
|
The main difference in general is that **QUIC seems to be a way to bring TLS to a lower level, while focusing on latency, while in Fenrir we focus a lot more on security and flexibility.**
|
|
|
|
... | ... | @@ -30,15 +33,16 @@ The main difference in general is that **QUIC seems to be a way to bring TLS to |
|
|
By having integrated encryption and authentication both QUIC and Fenrir do not 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 30-40 bytes.
|
|
|
QUIC is more difficult to understand, since basically all of its header fields are completely optional and with varied length. Just for an estimate, a QUIC header can go from 1 byte to 60 bytes.
|
|
|
QUIC is more difficult to understand, since basically all of its header fields are completely optional and with varied length. Just for an estimate, a QUIC header can go from 9 byte to 60 bytes.
|
|
|
|
|
|
QUIC format can sometimes be more efficient than Fenrir, but at the cost of a more difficult parser.
|
|
|
Fenrir also includes the option of multiple alignments, while in QUIC everything is byte-aligned.
|
|
|
|
|
|
### Features
|
|
|
|
|
|
In QUIC all multiplexed streams are ordered, reliable streams. As a hack you can have unreliable streams by exploting the implicit stream creation: send data in a new stream, and then forget about that stream. This way it is not tracked as a reliable stream.
|
|
|
The problem with this approach is that it can not span multiple packets and is actually just a hack.
|
|
|
In QUIC all multiplexed streams are ordered, reliable streams. There currently is a draft to introduce unreliable transport, but it is not in the main documentation yet.
|
|
|
|
|
|
Due to having only reliable stream, QUIC has implicit stream creation: just send the data in a new stream, without notifying the stream creation.
|
|
|
|
|
|
In Fenrir you need to explicitly create each stream, but you can choose any combination of (un)reliable, (un)ordered delivery, both stream and datagram.
|
|
|
|
... | ... | @@ -52,13 +56,13 @@ The connection setup is a 4-way handshake with cookies to avoid SYN flood attack |
|
|
|
|
|
QUIC supports a 0-RTT reconnection. Fenrir does not do less than 1-RTT by design. But maintaining long timeouts for the connections will have the same result. 0-RTT connections are avoided in Fenrir as they leave way too many options for amplification attacks.
|
|
|
|
|
|
While QUIC supports 0-RTT connections, applications need to be designed to avoid amplification attacks by requiring an ulterior RTT before sending a lot of data. Relying on applications to implement the correct security features for such as a feature is bound to create a lot of amplification attacks.
|
|
|
While QUIC supports 0-RT connections, applications need to be designed to avoid amplification attacks by explicitly requiring an ulterior RT before sending a lot of data. Relying on applications to implement the correct security features for such as a feature is bound to create a lot of amplification attacks.
|
|
|
|
|
|
Here we can see what we meant before by "latency vs security". To reduce latency QUIC does neither a full PFS (next section), or have a full protection against replay attacks. As you can read in the [QUIC Crypto](https://docs.google.com/document/d/1g5nIXAIkN_Y-7XJW5K45IblHd_L2f5LTaDUDwvZ5L6g/edit) document:
|
|
|
|
|
|
> QUIC doesn’t provide replay protection for the client’s data prior to the server’s first reply. It’s up the application to ensure that any such information is safe if replayed by an attacker.
|
|
|
|
|
|
This is the same old mistake of pushing security details on the developers. Developers will (unknowingly) ignore it, until everyone will use a common framework that limits QUIC features to the safest subset. Same as happened with OAuth.
|
|
|
This is the same old mistake of pushing security details on the developers. Developers will (unknowingly) ignore it, until everyone will use a common framework that limits QUIC features to the safest subset. The same as happened with OAuth.
|
|
|
|
|
|
|
|
|
## Perfect forward secrecy
|
... | ... | @@ -72,27 +76,31 @@ As long as the ephemeral public key is changed quickly (let's say, every couple |
|
|
An other example of latency vs security. To decrease latency, the initial data sent by the client is NOT protected by PFS. Instead, PFS is set up at the first packet sent by the server. The client can, however, still send non-PFS data in this period of time. The first bytes of a connection might contain login data or other information, and I see no reason to treat this differently, so in Fenrir such behaviour is avoided by design.
|
|
|
|
|
|
|
|
|
### PFS on resumed connections
|
|
|
### PFS on "resumed" connections
|
|
|
|
|
|
By "resumed" here we merely mean that the client did a connection once, then closed, then opened a new one not much later.
|
|
|
|
|
|
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.
|
|
|
|
|
|
Connection resumption is not a thing in Fenrir (yet), as we just need to give longer timeouts, and there will be no need for further handshakes.
|
|
|
Connection resumption is not a thing in Fenrir (yet), but the directory-synchronized method could implement a similar mechanism, while avoiding 0-RT
|
|
|
|
|
|
## Forward Error Correction
|
|
|
|
|
|
This is a very nice improvement of QUIC over previous protocols:
|
|
|
This *was* a very nice improvement of QUIC over previous protocols:
|
|
|
|
|
|
Basically every 2 packets QUIC sends an other packet which is the XOR of the previous 2 (like RAID-4). So if one was lost, the receiver can reconstruct it without asking a retransmission.
|
|
|
Basically every 2 (or more) packets QUIC sends an other packet which is the XOR of the previous packets (like RAID-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. However it is not flexible enough, so I created the [libRaptorQ](https://www.fenrirproject.org/Luker/libRaptorQ) project implements the RaptorQ algorithm that generalizes the same concept over any number of source packets and repair packets. It's not as quick as a single XOR, but much more flexible.
|
|
|
This is actually a good idea, and I decided to learn from it and put it into Fenrir. However it is not flexible enough, so I created the [libRaptorQ](https://www.fenrirproject.org/Luker/libRaptorQ) project implements the RaptorQ algorithm that generalizes the same concept over any number of source packets and repair packets. It's not as quick as a single XOR, but much more flexible.
|
|
|
|
|
|
The FEC has been later removed from QUIC, on the grounds that it could not provide enough protection to really matter. By my experiment RaptorQ instead is a huge advantage when the network loses a lot of packets (5% and more), and an even bigger advantage on High-loss, high-latency connection.
|
|
|
|
|
|
## 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. (in QUIC the id length is actually variable)
|
|
|
|
|
|
QUIC stream identifiers are actually larger (1-8 bytes) then Fenrir's (4 bytes), but really, today's applications use just one stream (TCP) for everything, 65534 streams should be enough. Even assuming it is not enough, introducing an other multiplexing layer before the application is trivial. Trying to get a proper priority out of all the streams is also an other problem itself.
|
|
|
QUIC stream identifiers are actually larger (1-8 bytes) then Fenrir's (2 bytes), but really, today's applications use just one stream (TCP) for everything, 65534 streams should be enough. Even assuming it is not enough, introducing an other multiplexing layer before the application is trivial. Trying to get a proper priority out of all the streams is also an other problem itself. Fenrir might move to 64bit connection identifiers, but currently I don't think it is a big improvement.
|
|
|
|
|
|
QUIC uses a 64-bit sequence number for its streams, while Fenrir has a 30-bit one, like extended TCP. Having a bigger sequence number is actually a good thing, as it helps a lot in high-latency-high bandwidth connections, such as satellite ones, but 30 bit should be enough for everybody. Putting together the stream multiplexing and the 30-bit counter already lets us have connections in the range of the Tb/s for satellite connections.
|
|
|
QUIC uses a 64-bit sequence number for its streams, while Fenrir has a 30-bit one, like extended TCP. Having a bigger sequence number is actually a good thing, as it helps a lot in high-latency-high bandwidth connections, such as satellite ones, but we hope 30 bit should be enough. Putting together the stream multiplexing and the 30-bit counter already lets us have connections in the range of the Tb/s for satellite connections.
|
|
|
|
|
|
### Limitations?
|
|
|
|
... | ... | @@ -106,11 +114,13 @@ Of course, you should not expect Fenrir to handle a multi-Gb buffer. The message |
|
|
|
|
|
## Proof of ownership
|
|
|
|
|
|
**NOTE:** I can't find this part anymore in the QUIC draft, was it removed?
|
|
|
|
|
|
This means that we want to be sure that the packet has not been spoofed.
|
|
|
|
|
|
QUIC uses the usual RTT method to be sure of IP ownership, 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 only makes sure that at least one RTT has been done before "trusting" an ip address.
|
|
|
Fenrir only makes sure that at least one RTT has been done before "trusting" an ip address. A message is sent to the new IP, and the answer can come back from any IP.
|
|
|
|
|
|
The difference here is that QUIC tries to do continuous IP-ownership checking. This is however already present in the form of the receiving transmission window.
|
|
|
The only sensible limit is a timeout on the last packet received for that IP. But the receiving window would be exhausted before the timeout anyway, so the only sensible option seems to drop an IP from the pool of the "trusted" IPs once the timeout associated with 2 receiving windows has expired.
|
... | ... | |