quicwg / quic-v2

A short specification of a trivial QUIC version 2

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Need to specify the update process

huitema opened this issue · comments

We now have some implementation experience, and got interop between 2 implementations. That's great, but the process was difficult because the transition is somehow under specified. There was a lot of discussion as issues with the compatible version negotiation draft:

These issues cannot be fully addressed in the compatible version negotiation draft, which has to be version independent. Instead, they need to be addressed in specific drafts. The V2 draft, for example, should specify exactly what happens during the version negotiation. My understanding is that when version negotiation succeeds, we will see something like:

  • Client sends a first flight composed of Version 1 initial packets
  • Server may send Version 1 initial packets containing acknowledgement, e.g., to manage losses of Initial packets
  • At some point, the server will have received and parsed the transport parameters, and decided to upgrade to V2
  • After that point, server will send version 2 packets (Initial, Handshake, 1RTT)
  • Client will receive version 2 packets and should be ready to process them before the negotiation completes
  • The transport parameters will arrive in V2 handshake packets, after which the negotiation is done.

There are quite a few potential issues that need resolution:

  1. As explained above, in case of successful negotiation, the client expects the server to start sending V2 packets asap. Shall it ignore V1 packets as soon as it received V2 packets? Should in check version numbers in Initial packets, in a process similar to key updates?
  2. If the client receives transport parameters on a version 2 packet, what shall it do if the chosen version is V1?
  3. And vice versa?
  4. If the server receives V2 handshake packets from the client, shall it conclude that the negotiation is successful?
  5. In case of session resumption, does the client resume using V1 or V2? I think the answer to that question depends on the content of the "supported versions" list provided by the server. If it includes V2, then the server is ready to receive V2 packets. If the server is part of a server farm with partial deployment of V2, it should not say that V2 is ready. The answer may also depend on local conditions at the client.
  6. If the client resumes using V1, it will send 0-RTT packets using V1. The server will receive these packets after the client's initial packets, and thus after receiving the transport parameters and completing the version upgrade. Should the server drop these packets? Or should it continue accept them until the handshake completes?
  7. On the client side, there will be a delay between completing the negotiation and finalizing the handshake. The client may want to send 0-RTT packets during that interval. Shall it send those using V1 or V2?

The most literal answer to your question is, "of course all v1 can be interchanged with v2, since they're identical". But I'm going to answer the more interesting question of what precise questions a new version has to answer.

AFAICT, in the v1->v2 case, (assuming all the support is present) there are four possible responses from the server:

  1. a v2 Initial with ACK and/or ServerHello
  2. a v1 Initial with ACK, followed by a v2 Initial with ServerHello
  3. a v1 Retry (a v2 Retry would also be correct, but silly for the server to do things that way)
  4. a v1 Initial with ACK, followed by nothing (because some of the client hello was lost)
    I believe this generalizes to all transitions v1->v_n.

So clearly the client can't draw any conclusions about the ultimate version until it sees the server hello, or a v2 packet of any kind. It can't fully authenticate the handshake until we get 1-RTT keys.

So to answer your questions:
(1) yes, ignore v1 once you get v2 -- you don't need the Initial ACK anyway
(2) and (3) if the chosen version in the TP doesn't match the QUIC header, this is a VN violation, no? Shouldn't this be handled in the VN draft?
(4) I would think that any client packet with v2 and the correct keys would do the trick.
(5) The two elements of this are the NEW_TOKEN token and the TLS session ticket. The hard part here is that the contents of this are not in any version spec; if QUIC and TLS implementations put version specific things in there, then it won't work. IIUC in general the session ticket wouldn't include anything derived from the version-dependent HKDF labels, so it ought to work.
(6) and (7) I believe the server has to handle v1 0RTT till the handshake is over, as it can't guarantee that 0RTT arriving after the 2nd flight was sent after that flight. The client could switch its 0RTT to v2 once negotiated -- I have no strong opinion if that complexity is worthwhile.

I don't think putting these responses in a PR is the right move -- I'd like to clarify what properly should go in the VN draft and what should rest here.

(1) yes, ignore v1 once you get v2 -- you don't need the Initial ACK anyway

Minor fix. In @huitema's example, ACK in V1 from the server is received by the client before any V2 packets. So, the client can handle it anyway.

(6) and (7) I believe the server has to handle v1 0RTT till the handshake is over, as it can't guarantee that 0RTT arriving after the 2nd flight was sent after that flight. The client could switch its 0RTT to v2 once negotiated -- I have no strong opinion if that complexity is worthwhile.

This is probably a good idea. We can say that 0RTT belongs to the previous connection of V1.

@huitema If you agree, let's implement this and do interop.

a v1 Retry (a v2 Retry would also be correct, but silly for the server to do things that way)

We need to prohibit v2 Retry since a v1-only client cannot retry if v2 Retry is received.

If the client receives transport parameters on a version 2 packet, what shall it do if the chosen version is V1?

When a client see V2 in a long header, it switches to V2 keys. This switch is allowed only once. After handshake is completed, the client checks if the version for keys and Chosen Version is the same.

OK, I will test the 0-RTT part internally first. There are timing issues in the server code, depending on whether the 0-RTT key is produced before the negotiation or after it.

@huitema The idea for 0-RTT works perfectly on my local tests. I will brush up the code tomorrow and set up a public server.