-
Notifications
You must be signed in to change notification settings - Fork 917
feat[tokio-quiche]: implement server-side support for 0-RTT #2267
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
base: master
Are you sure you want to change the base?
Conversation
| _ctx: &mut ConnectionStageContext<A>, | ||
| ) -> ControlFlow<QuicResult<()>> { | ||
| if qconn.is_established() { | ||
| if qconn.is_established() || qconn.is_in_early_data() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what helps us transition to Application space so we can then handle the early_data request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about your comment about requests after early data having trouble. Is there something that prevents the handshake from continuing and completing after taking a break to handle early data?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth adding some logging on handshake completion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about your comment about requests after early data having trouble. Is there something that prevents the handshake from continuing and completing after taking a break to handle early data?
Thats exactly what I need to debug next. My mental model is that it should invoke the work_loop and continue so need to double check that and compare against the no early_data variation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The primary concern I see here is that work_loop's wait phase will not call wait_for_quiche, which wakes the IOW when a TLS callback progresses, in the RunningApplication phase. It depends solely on the AOQ's wait_for_data implementation.`
I'm not super familiar with early data, is it possible that the 0-RTT request/response finishes before the PK callback? If so, we may delay the handshake until the next received packet/Quiche timer fires, rather than when the callback actually completes. From Boring docs it sounds like there's no guarantee about that:
As a server, if early data is accepted, SSL_do_handshake will complete as soon as the ClientHello is processed and server flight sent. SSL_write may be used to send half-RTT data. SSL_read will consume early data and transition to 1-RTT data as appropriate. Prior to the transition, SSL_in_init will report the handshake is still in progress. Callers may use it or SSL_in_early_data to defer or reject requests as needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly: wait_for_quiche is used to progress the TLS Handshake callbacks. In RunningApplication phase, we do not call the wait_for_quiche. The concern is that we might stall the Handshake we transition to RunningApplication in early data (since technically the Handshake is not complete).
We currently use quiche for two callbacks private_key_callback (not called when we resume) and async_select_cert_callback (called when before processing ClientHello). So for our usecase this the Handshake should not stall.
One way to make this clean would be to and another phase Handshake -> ZeroRtt -> RunningApplication. But that doesn't seem necessary at the moment. I'll leave a comment documenting this behavior and something we might need to visit if we decide to use more callbacks.
| _ctx: &mut ConnectionStageContext<A>, | ||
| ) -> ControlFlow<QuicResult<()>> { | ||
| if qconn.is_established() { | ||
| if qconn.is_established() || qconn.is_in_early_data() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about your comment about requests after early data having trouble. Is there something that prevents the handshake from continuing and completing after taking a break to handle early data?
c0a7cad to
f5b3c4e
Compare
5a15fee to
2635dff
Compare
2635dff to
95b6031
Compare
95b6031 to
e577935
Compare
e577935 to
280f94a
Compare
| _ctx: &mut ConnectionStageContext<A>, | ||
| ) -> ControlFlow<QuicResult<()>> { | ||
| if qconn.is_established() { | ||
| if qconn.is_established() || qconn.is_in_early_data() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The primary concern I see here is that work_loop's wait phase will not call wait_for_quiche, which wakes the IOW when a TLS callback progresses, in the RunningApplication phase. It depends solely on the AOQ's wait_for_data implementation.`
I'm not super familiar with early data, is it possible that the 0-RTT request/response finishes before the PK callback? If so, we may delay the handshake until the next received packet/Quiche timer fires, rather than when the callback actually completes. From Boring docs it sounds like there's no guarantee about that:
As a server, if early data is accepted, SSL_do_handshake will complete as soon as the ClientHello is processed and server flight sent. SSL_write may be used to send half-RTT data. SSL_read will consume early data and transition to 1-RTT data as appropriate. Prior to the transition, SSL_in_init will report the handshake is still in progress. Callers may use it or SSL_in_early_data to defer or reject requests as needed.
280f94a to
3905c05
Compare
|
@evanrittenhouse 👏 helped confirm that we want to record the handshake duration as soon as we resume the early connection. @evanrittenhouse and I discovered that we set the handshake duration right after resumption with 0-rtt. Wondering if this is ok or if we want to record the duration when the full handshake finishes. https://github.com/cloudflare/quiche/blob/master/tokio-quiche/src/quic/io/worker.rs#L787-L788 |
7b4fd49 to
942bee3
Compare
This PR adds a setting to enable 0-RTT resumption and early data processing for the server. Early data uses 0-RTT keys, which are established from a previous session data (aka. session resumption). The most obvious downside of this is the ability for an attacker to replay a request to the server. Application therefore need to be careful when enabling 0-RTT and processing early data requests. For more information see BoringSSL docs: https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#Early-data
942bee3 to
41d6be1
Compare
This PR adds server support for 0-RTT. This is done by transitioning the Handshake to Application when we have 0-RTT keys. The PR also adds an extension header IsInEarlyData to forward the early data request status so application can detect when a request was received with 0-RTT keys (and take appropriate security precautions).