libp2p / libp2p/go-libp2p

quic: use context to allow sending of 0-RTT data

Open
#1,533 6 comments 0 reactions 0 assignees View on GitHub

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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.