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
Describe a new version negotiation mechanism which allows for #1755
Conversation
no-cost negotiation as long as the client and server support a common version. It also removes a lot of text.
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.
I like the approach, though I want to read it a few more times to make sure nothing from the old text is lost.
- Should there be an issue for this? 2) Should this be discussed in NY?
@ianswett: yes, we should discuss in NY. I will defer to the chairs for the need for an issue. |
Am I correct in assuming that resumption will be forbidden when the proposed mechanism is used? I ask this because if we forbid that, the only things that need to be processed in a different version becomes the Initial packet and the CRYPTO frame. |
@kazuho: I would think the client would be allowed to resume but the server would have to reject resumption/0-RTT if it changed version |
I think an issue for this would be a good idea. I'm not sure that I understand what constraints on the two versions are required in order to allow this approach to work. Consider the case where only two versions are supported, A and B. The client sends an INITIAL packet containing the ClientHello (or the like) encoded with A, but indicates that it also supports B. The server and client both prefer B, so the server decide to upgrade to B. Are we guaranteed that everything needed for B will be in the A ClientHello? Could the TLS handshake mapping change between A and B is some way that would cause problems here? What about 0-RTT data? What if between A and B we changed the stream mapping / numbering? The client would have created (and sent) streams allocated with the logic of A but which would be incorrect for B? It seems really hard to guarantee that there are no such changes between A and B. I think there are simpler solutions to the problem this PR intends to solve:
|
Thank you for the clarification. Makes sense to me. I like the idea behind the PR; to open the possibility of future versions of QUIC accepting v1 Initial packets without spending extra round-trip. Current approach does not allow that, and that will hinder us from introducing v2. |
FWIW, my assumption is that the only constraint would be that the TLS protocol version needs to be compatible. Consider the case where you want to send a QUICv1 Initial packet that can be upgraded to v3. From the Initial packet, the v3 server needs to extract the initial flight of the TLS handshake (i.e. ClientHello) and the elements that would have existed in the v3's Initial packet. It is obvious that the TLS handshake transcript can be extracted. The other elements can be transmitted as a TLS ClientHello extension. |
to support (most likely the oldest common version). | ||
|
||
* A list of versions which the client supports in the | ||
"supported_versions" transport parameter). |
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.
trailing paren
|
||
* A packet version which indicates which version it has been encoded | ||
with. This SHOULD be a version which the client expects most servers | ||
to support (most likely the oldest common version). |
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.
I'd drop the parenthetical here.
If the server understands the packet version -- even if it is not its | ||
most preferred version -- then it deprotects the packet and selects | ||
the most preferred version out of the client's supported versions | ||
list, and responds with that version. This allows a client and server |
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.
Aside from sentence construction here, which needs work, I don't understand how you believe this should work. If you believe that a server can continue a connection, how can it continue from an Initial taken from a different version?
I'm not strongly opposed to this as an optimization, but it doesn't feel necessary for QUICv1. You remove a lot of text, but it's adding a second layer of version negotiation -- I would expect that it needs more text, and I'm not convinced the text you removed is obsoleted by adding a second way to negotiate. |
The big loser here is the validation of version negotiation. I think that most of that is stuff we want to lose. By having all the client's supported versions available to the server we lose a lot of the complication that the text was addressing. I think that we do need new text to describe the properties we are looking to obtain and how we obtain them, but that should be short. It appears as though the proposed text is a little too lean (the rationale for having transport parameter format stability is gone, for instance). |
IIUC, the risk here is that if we have a client and server that support both QUIC v1 and vX (a future version of QUIC that does not use TLS), we cannot detect downgrade attack that forces the peers to use v1 instead of vX. Are we fine with that? If not, I might prefer retaining the current approach in v1 and consider introducing the proposed approach in v2 (my understanding is that this type of version negotiation can be introduced afterwards, like we introduced supported_versions in TLS 1.3). |
Any risk of a downgrade attack sounds like a big loose. Especially if the only concern is to save a few messages during a few hours of deployment of a new server. Otherwise, if it can be done safely, by all means... The IoT scenario is very real. For example, the author of the new BearSSL is concerned about the cost of TLS 1.3 on constrained devices and believe TLS 1.2 will live on. This will consequently lead to a different version of QUIC for such devices, if he is right. |
Kazuho, I think this approach only works if the server supports both the version the client tries intitially and another version the client offers. The client can choose to only offer alternate versions it prefers, but does not know if the server supports. I believe that mitigates the downgrade attack? If the client tries v1 and the server only supports v0, the server is going to have to send a VN anyway I think? |
@ianswett The case I am concerned is like below. Client and server supports both v1 and vX. Client prefers using vX, and sends Initial using vX format. Middlebox intercepts that, and injects a Retry that only allows v1. In response, client sends Initial using v1 format. TP will still include v1 and vX. Now the server sees that the client supports both v1 and vX, but does not have a clue that the client preferred using vX. Hence the handshake succeeds using v1. At this point, downgrade attack succeeds. The key observation here is that it is only the client that knows what the initially tried version is. Therefore, we currently require the client to verify if there has been an attempt to downgrade. The proposed change removes that requirement without a replacement. If we want to let the server select the version, I think that we should require the client to send it's original version number using TP so that the server can determine if there was a downgrade attack. |
nit: Above, you meant the middlebox injects a VN, not Retry, correct? We could force the client to list the initially chosen version first or last as well, if we don't want another transport parameter. My thinking was the client would only list other versions it likes as well or better than the version it initially tried. ie: it'd try 1, but also list 2. In my mind, the question of timing comes down to whether we think this will be helpful to upgrade from draft IETF versions to the 'final' v1 . I'd like to think the frames are not likely to change prior to v1 so that feature won't need to be exercised, but that's probably wishful thinking. |
I think we don't want to remove the client's initially-offered version or the server's list of other supported versions -- they're there for valid reasons and are still needed. The client's original version is used for the server to ensure that the VN wasn't injected. The server's other supported versions are useful for the client to remember and pick a more-preferred version next time (especially if that more-preferred version uses a different handshake). This optimization should strictly add to the VN information in the handshake, with a list of compatible version the server could switch to in its response. (The suggestion that such compatible versions would include near-final draft versions and the final RFC is definitely intriguing from a deployment standpoint, incidentally.) |
{{iana-transport-parameters}}. | ||
|
||
|
||
### Version Negotiation Validation {#version-validation} |
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.
Build failure is because you've removed this section without updating the other places in the draft that reference it. (Incidentally, the pre-commit hooks should have blocked you from committing something that doesn't build -- can you run make update
to make sure that's installed?)
Guidelines on how to decide which version is preferable? Is that a local configuration? Or list order in TP? An IoT device might be able to speak all versions, but have vastly different preferences from a high powered server. |
I think preference is always in the hands of the one who switches, with ability to constrain options on the other party. So I'd frame it as:
There's not necessarily an obligation to disclose every version you're capable of speaking; you might only disclose the ones you want a peer to use. |
This does require that it send its original version number. The client lists all its supported versions. We can - as is customary - insist that the client puts its preferences first. But a consequence of this design is that the server ultimately decides which version is used. |
Yes. Thank you for noticing that.
That's certainly an option, but then you cannot detect downgrade attacks that happen between the wire-compatible versions too. IMO, it is beneficial to define two version negotiation mechanisms (i.e. one uses VN and one uses the proposed method) as independent as possible, and that leads me to think that the client should include all the versions it can use in the TP, regardless of what the interaction using VN was.
That makes sense. Thank you for pointing that out. |
This is an interesting idea, but it also strikes me as the kind of minor optimization that shouldn't make the cut at this stage in the process. I understand @kazuho 's point that it might ease v2 transition, but the VN code has been stable for a long time and there are lots of things to think about here. This also puts version choice in the hands of the server, rather than client. I'm not sure how I feel about that. If clients are picking a version based on their resource constraints, then this is a bad thing. |
@martinduke FWIW, my view is that the downgrade attack protection in the current VN design is corrupt. I have filed #1810 that explains the issue. |
As discussed in #1758, we only need to allow rate limiting. However, the particular example I draw on will become critical if we adopt the proposed changes to version negotiation in #1755 (or something like it), because the only packet a server can confidently respond to with Version Negotiation in that case is the Initial. If we adopt an iteration of #1755, then this text would need to be expanded to explain that also. Closes #1758.
This introduces the design that proposed by ekr prior to the NY interim. In this design, the client advertises the list of versions it supports in its transport parameters. The server is permitted to select a "compatible" version and proceed as though the client selected that version. The main advantage of this approach is seamless upgrade between compatible versions without the extra round-trip imposed by Version Negotiation. This will be especially useful when we move from pre-release versions (0xff0000xx) to the final version. Closes #1773, #1755.
See #1901 for a less bitrotten version of this. |
no-cost negotiation as long as the client and server support
a common version. It also removes a lot of text.