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
Connection ID DT output #1742
Connection ID DT output #1742
Conversation
draft-ietf-quic-transport.md
Outdated
previously used SHOULD also switch to sending with a different connection ID. | ||
This can help to ensure that different connection IDs will be used in both | ||
directions when an endpoint migrates to a new path or changes connection ID on | ||
an existing path. |
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.
Technically, it doesn't do anything for changes on the existing path, but that's okay because the session is linkable anyway if you're on an existing path.
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 guess the problem is that this paragraph implies the remote peer did not change CID but the address changed (perhaps NAT binding). If we switch CIDs, does it really require the remote end to switch CIDs? The likability problem is still there, I think.
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.
It's not always the case that use of an existing path implies linkability. Though it might be a strong signal, if I'm behind a NAT with a large number of other people, I can imagine the NAT being used as an mixing point. Changing connection ID in that context might re-establish anonymity within that set. Especially if the NAT understands connection IDs and I am able to use one for packets I receive as well. In many cases we think about, the NAT is small and the value of re-mixing low, but you can imagine building that sort of aggregator for privacy purposes.
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.
In practice, that recommendation amounts to the server initiating a migration upon receiving packets from a new client address, so that a given pair of CID is tied to a single pair of addresses. That can work, but we have to consider security issues. Addresses are outside the cryptographic envelope, attackers can take good packets and just replace the address by something else. That mean attackers can easily trick servers into starting migrations.
I am not sure of the balance between aggravated DOD risk and moderate privacy gain. The beans are already spilled in the packet from the client with the changed address and the constant CID. If we do nothing, the client will notice that its own address changed upon receiving the first reply from the server. It can then chose to start a migration. That seems more robust.
One item to note is that we've adopted EKR's suggestion to use IP:port (collectively "address" as in the migration section) changes instead of CID changes as the trigger to change your own CID. Here's why:
The case we actually need to cover is ensuring that, if an endpoint changes address and CID at the same time, the peer absolutely does not respond with the old CID. Any rule that produces this is sufficient, even if it also produces some gratuitous changes along the way. Part of what led to the changes in -13 is that switching on CID change makes it hard to avoid looping. Switching on endpoint address covers the scenario we need without requiring a fixed ordering of CIDs. |
@MikeBishop this make sense, but in symmetric settings, both sides could have NAT rebindings, so there could a case for preemptive CID change at either endpoint after idletime - but perhaps that is a separate issue. |
That's already a recommendation in the existing text -- this is strictly talking about how to ensure that the CID coming back from the peer doesn't link, but also doesn't trigger a new CID rotation, which triggers a rotation, which triggers.... |
draft-ietf-quic-transport.md
Outdated
the connection with at least one connection ID to use when sending. An endpoint | ||
SHOULD supply its peer with additional connection IDs via NEW_CONNECTION_ID | ||
frames. While each endpoint can choose how many connection IDs to issue, a | ||
recommended number of outstanding connection IDs is eight. |
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 wonder if recommending a specific number is helpful. Do we have any operation experience about suggesting 8?
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 think that 8 is the right recommendation, but we should contextualize it more. The primary consideration being that it is important to support a number of failed connection migrations on the way to a successful migration.
That context is later, so I think we should just move this recommendation.
draft-ietf-quic-transport.md
Outdated
previously used SHOULD also switch to sending with a different connection ID. | ||
This can help to ensure that different connection IDs will be used in both | ||
directions when an endpoint migrates to a new path or changes connection ID on | ||
an existing path. |
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 guess the problem is that this paragraph implies the remote peer did not change CID but the address changed (perhaps NAT binding). If we switch CIDs, does it really require the remote end to switch CIDs? The likability problem is still there, I think.
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.
Obviously, I think that this is a good balance of the concerns, because I was involved with the decision. I do have some editorial concerns that.
I'm willing to help address these. I suggest that we start with a round of discussion, during which we might decide to split off some new issues.
draft-ietf-quic-transport.md
Outdated
the connection with at least one connection ID to use when sending. An endpoint | ||
SHOULD supply its peer with additional connection IDs via NEW_CONNECTION_ID | ||
frames. While each endpoint can choose how many connection IDs to issue, a | ||
recommended number of outstanding connection IDs is eight. |
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 think that 8 is the right recommendation, but we should contextualize it more. The primary consideration being that it is important to support a number of failed connection migrations on the way to a successful migration.
That context is later, so I think we should just move this recommendation.
draft-ietf-quic-transport.md
Outdated
previously used SHOULD also switch to sending with a different connection ID. | ||
This can help to ensure that different connection IDs will be used in both | ||
directions when an endpoint migrates to a new path or changes connection ID on | ||
an existing path. |
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.
It's not always the case that use of an existing path implies linkability. Though it might be a strong signal, if I'm behind a NAT with a large number of other people, I can imagine the NAT being used as an mixing point. Changing connection ID in that context might re-establish anonymity within that set. Especially if the NAT understands connection IDs and I am able to use one for packets I receive as well. In many cases we think about, the NAT is small and the value of re-mixing low, but you can imagine building that sort of aggregator for privacy purposes.
draft-ietf-quic-transport.md
Outdated
use by the endpoint when sending packets until the connection ID is retired by | ||
the endpoint. Endpoints can choose to stop using a given connection ID to send | ||
packets at any time and signal this to the issuing endpoint via a | ||
CONNECTION_ID_FINISHED frame. This frame indicates the connection ID that is no |
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 don't like this name (never have). But until I read this text again and saw it use "retire", I didn't have an alternative I liked enough to suggest. RETIRE_CONNECTION_ID is better (not awesome, but certainly better).
Yes, that's opinion. Also, don't bother changing it. I am prepared to do that.
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.
Sure, RETIRE_CONNECTION_ID works just as well. 😄
draft-ietf-quic-transport.md
Outdated
NEW_CONNECTION_ID frame ({{frame-new-connection-id}}). | ||
|
||
Retiring a connection ID using the CONNECTION_ID_FINISHED frame invalidates any | ||
stateless reset tokens associated with that connection ID. |
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.
As an open issue, we should decide how long to allow the old token to be effective. I would suggest that we use the same 3xRTO timer for that as well. Then we have 3xRTO everywhere in this.
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.
+1, I like moving towards 3xRTO for everything
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 think it's correct as written, actually, though we could make it more explicit if needed. This is the complementary case of when the recipient should stop accepting packets with the old CID.
If a packet with the old CID was delayed and the recipient drops the CID immediately upon receipt, you'll get a SR that you ought to ignore. So unless we're also adding a 3xRTO requirement on the server to continue accepting the retired CID, the sender needs to immediately stop recognizing the SRT associated with the CID. You might miss a SR from an old packet if the race lands wrong. But the packet being sent now has a new, still-valid CID and will presumably elicit a current SR of its own, so that's okay.
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 would actually disable the reset token asap. The only down side of doing that is to fall back to timer based termination if the connection breaks. But we probably need more text on the behavior of the reset token. Assume that a path is defined by a pair of CID. At any given point, a node will have a "main path" on which it is sending data, and a set of paths in various alternate paths in different stages of validation. Let's look at the following scenarios:
- Node sends a normal packet, on the main path, and receives back a reset.
- Node sends a probe with a fresh CID and new addresses and receives back a reset
- Node sends a probe response with a fresh CID in response to a probe and receives back a reset
- Node has parked an old path that it does not actively use and receives a reset on that path.
Do we want to treat all these scenarios the same, as in tear down the connection? Or do we want to just accept resets on the path that is actively used?
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 think we will have an interesting conversation. My main concern is whether to introduce a concept of paths, i.e. pairs o connection IDs. It would simplify my code significantly, rather than trying to implement paths using low level components like NEW CONNECTION ID, PATH CHALLENGE and PATH RESPONSE.
draft-ietf-quic-transport.md
Outdated
previously used SHOULD also switch to sending with a different connection ID. | ||
This can help to ensure that different connection IDs will be used in both | ||
directions when an endpoint migrates to a new path or changes connection ID on | ||
an existing path. |
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.
In practice, that recommendation amounts to the server initiating a migration upon receiving packets from a new client address, so that a given pair of CID is tied to a single pair of addresses. That can work, but we have to consider security issues. Addresses are outside the cryptographic envelope, attackers can take good packets and just replace the address by something else. That mean attackers can easily trick servers into starting migrations.
I am not sure of the balance between aggravated DOD risk and moderate privacy gain. The beans are already spilled in the packet from the client with the changed address and the constant CID. If we do nothing, the client will notice that its own address changed upon receiving the first reply from the server. It can then chose to start a migration. That seems more robust.
draft-ietf-quic-transport.md
Outdated
|
||
An endpoint that retires a connection ID should retain knowledge of that | ||
connection ID for a reasonable time after sending the CONNECTION_ID_FINISHED | ||
frame, or until that frame is acknowledged. A recommended time is three times |
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.
@martinthomson do we still have a reset risk if the client retires the stateless reset value that it received with the retired connection ID?
draft-ietf-quic-transport.md
Outdated
NEW_CONNECTION_ID frame ({{frame-new-connection-id}}). | ||
|
||
Retiring a connection ID using the CONNECTION_ID_FINISHED frame invalidates any | ||
stateless reset tokens associated with that connection ID. |
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 would actually disable the reset token asap. The only down side of doing that is to fall back to timer based termination if the connection breaks. But we probably need more text on the behavior of the reset token. Assume that a path is defined by a pair of CID. At any given point, a node will have a "main path" on which it is sending data, and a set of paths in various alternate paths in different stages of validation. Let's look at the following scenarios:
- Node sends a normal packet, on the main path, and receives back a reset.
- Node sends a probe with a fresh CID and new addresses and receives back a reset
- Node sends a probe response with a fresh CID in response to a probe and receives back a reset
- Node has parked an old path that it does not actively use and receives a reset on that path.
Do we want to treat all these scenarios the same, as in tear down the connection? Or do we want to just accept resets on the path that is actively used?
Added |
The remaining issue here is the re-introduction of a sequence number, which will work as follows:
For example:
If you've got a sequence number you can keep track of the highest sequence that you've gotten and, since this one will not advance the sequence number, you can safely ignore the duplicate NEW_CONNECTION_ID frame. |
This reverts commit a22f0aa.
draft-ietf-quic-transport.md
Outdated
during the handshake. Subsequent connection IDs are communicated to the peer | ||
using NEW_CONNECTION_ID frames ({{frame-new-connection-id}}). While each | ||
endpoint independently chooses how many connection IDs to issue, a recommended | ||
number of outstanding connection IDs is eight. |
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.
endpoints SHOULD provide and maintain at least 8 connection IDs......
draft-ietf-quic-transport.md
Outdated
ID used on different paths. To fulfill this privacy requirement, endpoints that | ||
An endpoint SHOULD ensure that its peer has a sufficient number of available and | ||
unused connection IDs. The endpoint can do this by always supplying a new | ||
connection ID when a connection ID is retired by its peer or when the endpoint |
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.
Maybe move the recommendation for 8 in between the two sentences here.
draft-ietf-quic-transport.md
Outdated
An endpoint that receives a packet with a different remote address or | ||
destination connection ID than previously used SHOULD also switch to sending | ||
with a connection ID that has not previously been used. The goal is to ensure | ||
absence of correlation between the pairs of client and server connection ID used |
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 goal is to ensure that traffic on different paths cannot be correlated.
draft-ietf-quic-transport.md
Outdated
receives a packet with a previously unused connection ID. Endpoints that | ||
initiate migration and require non-zero-length connection IDs SHOULD provide | ||
their peers with new connection IDs before migration, or risk the peer closing | ||
the connection. |
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.
closing the connection...when they run out of connection IDs.
draft-ietf-quic-transport.md
Outdated
: If both endpoints change connection ID in response to seeing a change in | ||
connection ID from their peer, then this can trigger an infinite sequence | ||
of changes. | ||
An endpoint can arbitrarily change the connection ID it uses for a peer to |
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.
s/arbitrarily//
draft-ietf-quic-transport.md
Outdated
connection ID for a period of time after sending the RETIRE_CONNECTION_ID frame, | ||
or until that frame is acknowledged. A recommended time is three times the | ||
current retransmission timeout (RTO) interval as defined in {{QUIC-RECOVERY}}. | ||
This prevents confusion from receiving retransmissions of a NEW_CONNECTION_ID |
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 prevents a retransmission of a NEW_CONNECTION_ID from incorrectly renewing a previously retired connection ID.
I've made some editorial fixes to the text, and also tried to reflect what we agreed on in NYC. |
- Merge ACK and ACK_ECN (quicwg#1801) - Add 2 transport parameters: max_ack_delay(12) and original_connection_id(13) (quicwg#981, quicwg#1710, quicwg#1486) - Remove sequence field from NEW_CONNECTION_ID (quicwg#1742) - Add RETIRE_CONNECTION_ID type (quicwg#1742)
Short summary:
An endpoint can issue as many CIDs to its peer as it chooses. It must always allow incoming packets on all outstanding CIDs. The only way to get rid of one from that "pool" is for the peer to indicate that the CID may be forgotten via the CONNECTION_ID_FINISHED frame.
On the receiving side, you remember all the CIDs you get from your peer and can generally use any that you like at any time. If you get more than you think you need, you can ignore some.
You're only allowed to use a CID on a single path, so you should probably retire any that you've moved away from via a _FINISHED frame.
Receiving a _FINISHED frame indicates that you should generally "replace" the retired CID. There are a few recommendations in this area, mostly to ensure that it's straightforward to keep your peer from running out of CIDs to use.