A QUIC Introspective
In my long-ago last post on HTTP/2, I said that I would follow up with a discussion of QUIC and why I believe it's important. Real life has been unfortunately busy, but it's time now.
Firstly, I don't intend to knock TCP. Not only has it served the Internet well for decades, it continues to evolve. Innovations like SACK, RACK, ACK timestamps, TCP Fast Open, and Multipath TCP are truly beneficial and I hope to see them widely deployed quickly.
But there's a fundamental problem here: TCP is well-known. Or rather, certain profiles of TCP are well-known. So well-known that some devices on the Internet panic if the TCP they see isn't the TCP they expect. Windows has supported TCP Fast Open for multiple releases now. With each release, an improved algorithm for side-stepping misbehaving hardware is designed -- and with each release, new hardware is found which misbehaves in different ways, and it gets disabled again.
Multipath TCP has faced similar deployment challenges, having to do extreme contortions to smuggle its new features in places that won't confuse the intermediaries which aren't expecting them.
The HTTP community has addressed this issue by adopting a more-and-more explicit stance that "new features" for some definition of that term will only be available in secure contexts. This is partially to motivate sites to move -- but also, realistically, a mitigation for the fact that these new features (new status codes, content encodings, and others) can and have broken proxies and other intermediaries in the past.
But TCP is totally unencrypted. Intermediaries can read traffic or modify it; attackers can inject additional packets or replay old ones. Sure, there's a checksum, but that only protects against accidental changes -- an intermediary who intends to change or forge a packet will just recompute the checksum.
QUIC encrypts from the start. Obviously, there's only so much you can do before you establish a shared encryption context, so QUIC progresses through multiple keys with increasing levels of security during the course of a handshake:
- Handshake keys guard against two attackers:
- Because the key is derived from an arbitrary value in the QUIC spec, an intermediary who does not speak this version of QUIC cannot accidentally misinterpret a newer version. They simply won't be able to read it.
- Because the key is derived from the (randomly-generated) Connection ID, it guards against forged packet injection by attackers who haven't seen the initial packets (off-path attackers).
- 0-RTT keys add protection against on-path attackers -- the packet can no longer be read by anyone but the intended recipient, but an on-path attacker can still capture and replay the packets in the future.
- 1-RTT keys add replay protection and forward secrecy.
That means QUIC will hopefully remain free to evolve over time. It also means that QUIC is free to adopt immediately innovations which have been designed for TCP but effectively suppressed by the very Internet they're meant to serve. The ability to send data in the first flight (typically called 0-RTT) provides massive improvements in the time required to set up connections.
QUIC is sometimes cast as a performance play, and it can be faster. But what it's doing, TCP can often do in theory. As a friend of mine is fond of saying, "In theory, there's no difference between theory and reality. But in reality, there's a vast difference." QUIC is a flexibility play.
I believe that, if we land this properly, QUIC is the future of the Internet. It's the very definition of a game-changer -- it modifies the rules, so that things we haven't thought of yet will become possible to experiment with and ultimately deploy.
It's not the next great idea -- it's what makes the next great idea possible.