multiaddr: Proposal: add a new codepoint for QUIC v1 (RFC 9000), and for future incompatible versions
Current Status
libp2p started deploying QUIC a few years ago, when RFC 9000 was not deployed yet. Back then, we deployed QUIC draft-29. Since node operators are slow to update their go-ipfs nodes, draft-29 is now the most deployed version.
| QUIC draft-29 | QUIC draft-29 + v1 | QUIC v1 | |
|---|---|---|---|
| QUIC draft-29 | ✔️ | ✔️ | ❌ |
| QUIC draft-29 + v1 | ✔️* | ✔️ | ✔️* |
| QUIC v1 | ❌ | ✔️ | ✔️ |
*: There’s a 1 RTT penalty if the version offered on the initial connection attempt doesn’t match the nodes version, as Version Negotiation is performed.
Currently, go-libp2p has support for QUIC draft-29 and QUIC v1. Since draft-29 is the most commonly deployed version (and supported by all nodes on the network), we use that version for dialing new connections.
What happens when rust-libp2p gains QUIC support
rust-libp2p is adding QUIC support, and quinn only supports RFC 9000. If we don’t do anything, this means:
- Legacy nodes (those supporting only draft-29) won’t be able to connect to rust-libp2p nodes. This is only fair. If you run seriously outdated software, you’ll have a bad time. You asked for it.
- rust-libp2p nodes won’t be able to tell which QUIC versions a node supports. It will try to connect to legacy nodes, and the QUIC connection will fail after 1 RTT.
- go-libp2p nodes now have two options:
- continue preferring draft-29. This will incur a 1 RTT penalty when connecting to rust-libp2p nodes, as we’ll need to perform version negotiation.
- prefer QUIC v1. This will remove the 1 RTT penalty, but will incur a 1 RTT penalty when connecting to legacy nodes. Given the large number of nodes, this might affect our TTFB metrics.
Proposal: add a new QUIC v1 code point
We could add a new code point for QUIC v1 (string representation: quicv1). The existing code point would be reinterpreted to mean QUIC draft-29.
Nodes that support multiple versions can (and should!) offer them on the same port. There’s no need to worry about demultiplexing, since QUIC packets contain the version number and any QUIC stack will be able to handle packets from different QUIC versions (if it’s a multi-version stack).
But what about QUIC v2
Does this mean that we need to add a new code point for every new QUIC versions? Wouldn’t that be wasteful. Yes and no. The IETF is currently working on specifying QUIC v2, and quic-go already has support for that QUIC version. We don’t need a new code point though, because QUIC v2 is a compatible version (to QUIC v1). The exact definition of what constitutes compatibility between QUIC versions is subtle, but as a rule of thumb, if there’s a transformation of the ClientHello from one version to a ClientHello of the other version, chances are that the versions are compatible. QUIC versions that use TLS 1.3 (or successors) are likely to be compatible. Using Compatible Version Negotiation (shipping as an RFC very soon), it is possible to do a version upgrade between two compatible versions without incurring any round trip penalty. Thus, it’s fine to continue advertising QUIC v1, as the connection can seamlessly be upgraded to v2 during the handshake.
Only when / if QUIC v2 becomes a dominant version on the internet, AND there are good reasons to not use QUIC v1 any more, would it make sense to introduce a v2 code point, so that compatible version negotiation can be skipped.
Hypothetical: an incompatible QUIC version is defined
A QUIC that uses a different handshake protocol than TLS 1.3 would almost certainly not be be compatible with QUIC v1. Assuming that libp2p would want to support both versions, it would make sense to introduce a new codepoint for that QUIC version, as we’d incur an additional roundtrip for version negotiation when nodes offer an unsupported version.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 17 (12 by maintainers)
Commits related to this issue
- quic: Use `quic-v1` codepoint With multiformats/multiaddr#145 the `quic` codepoint should be interpreted as QUIC draft-29. For QUIC v1 (RFC9000) the new codepoint `quic-v1` should be used. Quinn sup... — committed to kpp/rust-libp2p by elenaf9 2 years ago
- feat: support /quic-v1 https://github.com/multiformats/multiaddr/issues/145 https://github.com/ipfs/kubo/issues/9410 License: MIT Signed-off-by: Marcin Rataj <lidel@lidel.org> — committed to multiformats/js-multiaddr by lidel 2 years ago
- feat: support /quic-v1 (#294) This PR adds support for `/quic-v1` which will be enabled by default in Kubo 0.18 (https://github.com/ipfs/kubo/issues/9417, https://github.com/ipfs/kubo/issues/9410).... — committed to multiformats/js-multiaddr by lidel 2 years ago
Thank you for your comprehensive response, @MarcoPolo!
That makes sense. The hope is that in the long term (as QUIC draft-29 is phased out), the
/quicstring representation will also slowly die. For the transition period, we should parse/quicas/quic-draft29. Once we disable draft-29 support (https://github.com/libp2p/go-libp2p/issues/1841 suggests a transition period of 6 months), we might also stop parsing/quic.No we still would want a new codepoint so that new nodes can know before dialing if the node speaks v1 or draft 29. If we don’t adopt a new codepoint and assume everyone uses quicv1 then you incur a penalty when communicating with (the many) old nodes.