Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Early data clarity #5

Draft
wants to merge 20 commits into
base: 1661
Choose a base branch
from
Draft

Early data clarity #5

wants to merge 20 commits into from

Conversation

gretchenfrage
Copy link
Owner

@gretchenfrage gretchenfrage commented Mar 29, 2024

I had a hard time getting 0-RTT actually working in practice. It escalated to me forking rustls so I could put in a bunch of print statements. In hopes of improving understandability and discoverability of this, this PR demonstrates the usage of 0-RTT in the client/server example, adds other features to the client/server example to facilitate 0-RTT testing, and adds and rewrites some of the doc comments. It does not actually change any quinn code or APIs.


Tests with emulated localhost latency set to 100 ms.

Baseline no-0RTT test

cargo run --example server ./
cargo run --example client -- https://localhost:4433/Cargo.toml --suppress
# > connecting to localhost at [::1]:4433
# > connected at 205.968523ms
# > first response byte at 407.806377ms
# > response received in 17.335µs - 13238.661 KiB/s

Basic 0RTT test

cargo run --example server ./ --0rtt
cargo run --example client -- https://localhost:4433/Cargo.toml https://localhost:4433/Cargo.toml \
	--suppress --0rtt
# > connecting to localhost at [::1]:4433
# > client rejected 0rtt conversion
# > connected at 204.259169ms
# > first response byte at 406.096949ms
# > response received in 17.567µs - 13063.824 KiB/s
# >
# > connecting to localhost at [::1]:4433
# > client accepted 0rtt conversion
# > server accepted 0rtt data at 203.783772ms
# > first response byte at 203.80829ms
# > response received in 14.531µs - 15793.283 KiB/s

Test: 0-RTT, but not 0.5-RTT

cargo run --example server ./
cargo run --example client -- https://localhost:4433/Cargo.toml https://localhost:4433/Cargo.toml \
	--suppress --0rtt
# > connecting to localhost at [::1]:4433
# > client rejected 0rtt conversion
# > connected at 204.57444ms
# > first response byte at 406.396568ms
# > response received in 18.739µs - 12246.769 KiB/s
# >
# > connecting to localhost at [::1]:4433
# > client accepted 0rtt conversion
# > server accepted 0rtt data at 203.518732ms
# > first response byte at 405.201436ms
# > response received in 15.87µs - 14460.755 KiB/s

Test: 0.5-RTT, but not 0-RTT

cargo run --example server ./ --0rtt
cargo run --example client -- https://localhost:4433/Cargo.toml --suppress
# > connecting to localhost at [::1]:4433
# > connected at 206.004094ms
# > first response byte at 407.890297ms
# > response received in 21.695µs - 10578.114 KiB/s

Test: 0-RTT rejected by server

cargo run --example server ./ --0rtt
cargo run --example client -- https://localhost:4433/Cargo.toml https://localhost:4433/Cargo.toml \
	--suppress --0rtt --stdin
# > connecting to localhost at [::1]:4433
# > client rejected 0rtt conversion
# > connected at 204.058676ms
# > first response byte at 405.903475ms
# > response received in 20.768µs - 11050.279 KiB/s
# >
# > connecting to localhost at [::1]:4433
# > client accepted 0rtt conversion
# > server accepted 0rtt data at 203.678514ms
# > first response byte at 203.706407ms
# > response received in 12.453µs - 18428.668 KiB/s

# Now I Ctrl+C the server process
# Now I start it again:
cargo run --example server ./ --0rtt

# Now I input into the client process:
# https://localhost:4433/Cargo.toml

# > connecting to localhost at [::1]:4433
# > client accepted 0rtt conversion
# > server rejected 0rtt data at 204.140098ms
# > first response byte at 405.921651ms
# > response received in 16.168µs - 14194.223 KiB/s

# Now I input into the client process:
# https://localhost:4433/Cargo.toml

# connecting to localhost at [::1]:4433
# client accepted 0rtt conversion
# first response byte at 204.068826ms
# response received in 26.044µs - 8811.711 KiB/s

gretchenfrage and others added 20 commits March 29, 2024 16:20
Subsequent commits will allow the user to achieve the removed behavior
manually and more flexibly.

- Removes concurrent_connections from ServerConfig, as well as
  corresponding check in early_validate_first_packet.
- Adds ConnectionError::CidsExhausted error, although it is not yet
  instantiated.
- Renames ConnectError variant TooManyConnections to CidsExhausted.
- Renames proto Endpoint internal method is_full to cids_exhausted.
- Adds method open_connections to Endpoint (both proto and quinn).
- Removes Endpoint method reject_new_connection from Endpoint (both
  proto and quinn).
- Deletes obselete tests concurrent_connections_full and
  reject_new_connections.
This commit factors out the two fields of a quinn::Endpoint's State
necessary to process a proto::Transmit into a new sub-struct,
TransmitState. This is to alleviate borrowing issues, because
proto::Transmit will soon be called from more call sites than
previously.

The bulk of this code change is just moving around existing code.

Co-authored-by: Dirkjan Ochtman <[email protected]>
This commit refactors the logic for a quinn_proto::Endpoint accepting
an incoming connection so that it constructs an explicit Incoming struct
containing all the necessary state to accept/reject/retry the
connection-creating packet. However, the external API stays the same.

The bulk of this code change is just moving around existing code.
Additionally, adds some gitignore lines I was using for coverage
testing.
This commit removes use_retry from the server config and provides a
public API for the user to manually accept/reject/retry incoming
connections before a handshake begins, and inspect properties such as
an incoming connection's remote address and whether that address is
validated when doing so.

In quinn-proto, Incoming is made public, as well as Endpoint's accept/
reject/retry methods which operate on it. The
DatagramEvent::NewConnection event is modified to return an incoming
but not yet accepted connection.

In quinn, awaiting Endpoint::accept now yields a new
quinn::Incoming type, rather than quinn::Connecting. The new
quinn::Incoming type has all the methods its quinn_proto equivalent has,
as well as an accept method to (fallibly) transition it into a
Connecting, and also reject, retry, and ignore methods.

Furthermore, quinn::Incoming implements IntoFuture with the output type
Result<Connection, ConnectionError>>, which is the same as the Future
output type of Connecting. This lets server code which was
straightforwardly awaiting the result of quinn::Endpoint::accept work
with little to no modification.

The test accept_after_close was removed because the functionality it
was testing for no longer exists.
This commit adds a new --block option to the server example to
illustate in a simplified way the general structure one would use to
implement IP address blocking with the new accept/reject/retry API.

For example:

    cargo run --example server ./ --listen 127.0.0.1:4433 --stateless-retry --block 127.0.0.1:8065
    cargo run --example client https://127.0.0.1:4433/Cargo.toml --host localhost --bind 127.0.0.1:8065

One thing to note is that that example places the reject condition
before the retry condition. This expends slightly less effort rejecting
connections, but does create a blocked IP address oracle for an attacker
who can do address spoofing.
This commit adds a new --connection-limit option to the server example
to illustrate how a user could implement a limit to the number of
connections open at a time with the new "incoming" API and
Endpoint::open_connections method rather than with the now-removed
concurrent_connections ServerConfig parameter.
Changes response_start to track the time of the first byte received.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant