quic: use context to allow sending of 0-RTT data
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 6.9k
- Forks
- 1.3k
- Avg merge
- 13d 21h
- Merged PRs (30d)
- 1
Description
Inspired by @vyzo’s and @aarshkshah1992’s recent approach of adding a value to a `context.Context` to signal if a stream should be opened via a relay, I'm wondering if a similar approach make sense for making use of QUIC’s 0-RTT feature?
## Background
When re-connecting to a server we've connected to before, QUIC allows us to send application data right away, without waiting for the handshake to finish. Data is encrypted with a key derived from the key used on the previous connection. However, 0-RTT data can be replayed by an attacker, and is therefore only safe to be used for idempotent data.
The doc linked in https://github.com/libp2p/go-libp2p/issues/1532 discusses approaches to make 0-RTT replay-safe. These approaches work, as long as the server properly implements them, however, there's no way for the client to enforce or even check this, so we probably don't want to rely on this.
A safer approach is to only use 0-RTT for application data that's replay-safe.
## Proposal
Make `Dial` return immediately when a 0-RTT connection is dialed. `OpenStream` will block until the handshake is done, unless a special "0-RTT-safe" value is set on the context, in which case it will return immediately. An application can then write 0-RTT data on that stream. After writing the idempotent data, it can then use context returned by [`HandshakeComplete()`](https://pkg.go.dev/github.com/lucas-clemente/quic-go#EarlySession) on the QUIC connection to wait for the QUIC handshake to complete.
Note that we'd have to add a similar method to the [`MuxedConn`](https://pkg.go.dev/github.com/libp2p/go-libp2p-core/mux#MuxedConn) interface (or maybe to the [`MuxedStream`](https://pkg.go.dev/github.com/libp2p/go-libp2p-core/mux#MuxedStream)?
By having application explicitly opt-in, we make sure that the default behavior of libp2p is a sane default: only send application data when the connection is properly secured and replay-safe. Furthermore, by using a special value on a context, this will naturally work on transports that don't support 0-RTT data.
### Open Questions
0-RTT can be rejected by the server for various reasons. In that case, the handshake falls back to a normal 1-RTT handshake, and all data sent in 0-RTT is ignored. This also invalidates all streams opened.
cc @Stebalien
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Dial and OpenStream entry points, then review the MuxedConn interface and HandshakeComplete context described in the proposal. Resolve how the context opt-in, interface change, unsupported transports, and rejected 0-RTT connections should behave; done means safe default 1-RTT behavior with explicit 0-RTT support.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- networking
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100