Change:
This enacts the proposal in on . Padding PATHRESPONSE and sending on the same path as PATHCHALLENGE helps ensure that the path MTU in both directions of the path is sufficient for the protocol to function. This is a nasty change; I'm personally quite unhappy about the prospect of implementing it, but it seems like the best option we have.
If we're going to go with a SHOULD on using the same path, then it makes sense to use a SHOULD on the padding piece as well.
The proposed PR bakes the assumption that paths should be symmetric. This might be an OK restriction for V1, but I hate seeing that baked in the code. There are several scenarios in which data can be send one way on a broadcast channel (e.g., satellite or DVB), while the other way is through a slower but symmetric channel. Supporting asymmetry requires testing each direction. The server, instead of changing the address at which it sends merely because it received data from the client on that new path, should perform its own Challenge/Response to validate the path. Since challenges have to be padded, this tests both continuity and MTU. The server learns that a path may exist by receiving packets on it; it only uses that path for sending if the path is validated. I guess this is something we will need to revisit as part of support for multipath.
NAME : It does not assume path symmetry, it tests for our MTU requirement for QUIC of 1200 bytes (URL).
NAME I agree with your concerns, which is why I asked for SHOULDs instead of MUST, but there may be other ways forward as well. That being said, the current proposal seems quite reliable, it's just not very flexible.
NAME By symmetry, I mean the assumption that the pair of source and destination addresses and ports used by the server is exactly the symmetric of the pair used by the client. This is not a completely natural assumption in QUIC, because peers are able to process packets received from any address and port, as long as the crypto works out.
NAME -- ah, ok, I follow. Yes, this is definitely limited to the scope of problem that we have right now. As you say, we might need to revisit this if we are to add use cases that we haven't yet considered.
NAME NAME Merging this, since the plan is to do consensus as part of LC.
In , we added the following sentence, but I think it does not make sense. Generally speaking, a receiver of a datagram cannot verify if the sender sent a full-sized datagram. That is because a datagram as a whole is not authenticated. Instead, we authenticate each of the QUIC packets that constitute the datagram. Therefore, if the sender sends a datagram consisting of multiple QUIC packets, it is (almost always) possible for a MOTS to take one of the QUIC packets, coalesce that with a few octets, and forward that datagram. That forwarded datagram would be smaller than the original datagram. Note also that a sender can send coalesced packet after the handshake too; see .
As a step forward, I think we should do the following: Regarding the sentence we added in , we should either a) change the rule to "MAY discard UDP datagrams less than 1200 bytes that carry ACK-eliciting Initial apckets", or b) delete the sentence, and Considering the fact that there could be other occasions in which we might want to require padding, either within the base drafts, or in some of the extensions, add a note to or somewhere that datagram size is not authenticated and cannot be enforced by the peer.
NAME I hate to make more changes, but I think your point is a good one. If a receiver does the enforcement that we added in -- of enforcing the datagram size -- that makes us vulnerable to this MOTS attack. The newly added text in hasn't shipped yet in a draft, so if we can get agreement, I'd like to take this in before we ship the next draft.
A timely reminder that making changes always results in making more changes and no matter how careful or small, there are almost always problems. This seems like a good proposed tweak, but this has to stop.
Let us discuss what purpose that "MAY discard" rule has and compare it to the issue. What is important for an endpoint is to ensure that its path to the peer is possible to forward packets and supporting at least minimal MTU to make QUIC work. I think that requirement lies on each endpoint to ensure that. Does the client need to enforce the server behavior for that verification? Is that a risk in itself that is greater, equal or less than the MOTS risk the enforcement has?
NAME NAME I totally agree that this has to stop. I'm sorry to have missed this point when working on ; I realized the problem when I was wondering about the MUST vs. SHOULD discussion in . That said, I do think that it would be a good idea to adopt the proposal in this issue. Let me go through the facts first. They are: An encrypted transport has to discard unauthenticated signals to prevent MOTS attackers from disrupting the connection. The size of the datagram is an unauthenticated signal throughout the lifetime of the connection. As noted above, this is the case for 1-RTT packets after handshake confirmation too. Due to these facts, "MUST NOT close, can discard" is a principle that we've always had. The reason we hadn't written it down is because we used to have only one requirement regarding datagram length, that correctly follow the principle, stating that "servers MUST discard non-full-sized datagrams containing Initial packets." But now that we have emerging consensus that datagrams carrying PATHCHALLENGE / PATHRESPONSE MUST be padded to full size (), we need to write down that the receiver cannot enforce that. Realizing that, I started to wonder if the "MAY close" rule that we added in has been correct. As NAME points out, is a change that has not shipped yet. It's a recent change due to an issue discovered during this IETF last call. I do not think we have official consensus yet. Therefore, I tend to think there would be less confusion if the next draft would contain: servers MUST pad datagrams carrying ack-eleciting Initial packets (the basis of ) endpoints MUST pad datagrams carrying PATHCHALLENGE / PATHRESPONSE frames () endpoints MUST NOT close a connection when receiving datagrams with size requirements () rather than having two different of rules for handling small-sized datagrams, of which one does not follow the principle.
Given we explicitly allow coalesced packets for PathMTU, I agree that closing the connection seems like the wrong thing to do. The PR looks sensible.
Agree with Ian. My plea for stopping was not about the fix (the fix here is good), but the original change. We would not have had this problem if we were able to accept that the protocol wasn't absolutely perfect.
NAME has described a way forward on the mailing list for this issue - are we good with that? If so, let's merge, close and do the consensus establishment during IETF LC.
This issue is somewhat similar to the issue with asymmetric path MTUs that NAME discovered in . Consider the following situation: Client and server are communication on one path. The client now probes a new path by sending a PATHCHALLENGE frame on the new path. The server responds with the PATHRESPONSE frame, but sends it on the old path. The client now considers the new path validated, and switches over to that path. If the PMTU in the direction from server to client is now smaller than 1200 bytes, it will never receive a packet from the server and the connection will time out. Even worse, if only small packets (for example ACK-only packets) make it through, this might delay the idle timeout indefinitely. While we could require the client to pad the packet containing the PATH_CHALLENGE to 1200 bytes, this still doesn't help us making sure that the return path also actually supports this packet size.
This is another interesting issue. In a nutshell, post-handshake path validation should confirm that PMTU is no less than 1200 bytes in both directions. But currently we do not require (or recommend) that the probe packets should be padded. Moreover, having such a requirement does not address the problem, because an endpoint is not required to send PATHRESPONSE on the path on which it received a PATHCHALLENGE.
So this issue is similar to with the added tweak that in migration each peer's verification is independent of each other. So the client will only know that it send path is working as currently specified. Only after the server have performed its PATH_CHALLENGE to the client for the new path will it know that it is actually working. Looking at how path validation is defined currently, with the addition of requiring padding to 1200 bytes the result for this case is that the new path will not validate for the server as none of the server's path challenges will arrive at the client and be echoed. Thus the server will declare the path as failed after max(3PTO, 6kInitialRtt). So the client will be able to use the new forward path but unless the old server->client path works the QUIC connection will fail. So I think with a PADDING requirement the slow or indefinite death of the connection will not occur. Looking at how connection migration is defined, the client will verify the path and attempt to migrate the connection by sending non-probe traffic. If the server do not send any non-probe traffic on the new interface until it have done path verification with 1200 bytes the connection migration will fail and the client will never see the server switch to using the new client source address for its communication. Thus, I think the only thing to make this fail consistently is to require padding of the path probes. Possibly one need to clarify that if one sends ACKs outside of path probes that are padded then one can end up in this state if the return path is not MTU capable.
I don't believe this is a PathMTU specific issue. The path could work perfectly in one direction and not in the opposite direction if the PATH_RESPONSE is sent on the old path. I thought this was a known issue for those implementing connection migration? NAME
I never understood why a PATH_RESPONSE was OK to send on the old path. Given that the client clearly wants the server to start using the new path (= a different IP address and port) it seems like the server has a really strong motivation to check that the client can actually receive stuff it sends there.
NAME agree there are only one reason. But the MTU can be verified to avoid failure here. NAME I think sending it back on the return path would avoid some failure cases. However, the peer endpoint still needs to do its own path verification. So do you think one should pad the PATH_RESPONSE carrying QUIC packet to verify the MTU on the return path for the endpoint requesting the path validation?
Why would the peer need to do another path validation? It is still sending to the same endpoint.
I agree that it seems all PATHCHALLENGE packets should be padded. I also cannot remember why it was allowed to respond with a PATHRESPONSE on a different path than the one challenged. I assume because path challenge/response is just treated as a unidirectional validation mechanism. One problem with padding PATH_CHALLENGE packets is in the case of rebinding. If the first/only packet you receive after rebinding is small enough, amplification protection would prevent you from sending a fully padded challenge packet back in response.
NAME because otherwise a malicious client can fake it. So if the client sends the server a PATHCHALLENGE to probe the path, it can spoof the source address, thus the server can't rely on it. So therefore the Server needs to send its PATHCHALLENGE and get a matching response before it has validated that path for transmission. So that requirement will not go away.
The migrating endpoint doesn't send a PATH_CHALLENGE, it just sends data (or whatever) on the new path. The other end sends the challenge, and the migrating endpoints sends the response. (In the case of a NAT, the migrating endpoint may not even know it is migrating, because a NAT rebinding might cause the path validation.)
NAME that is not the only way. Your way will occur when one have a NAT rebinding for example, but a client can test a path prior to migrating to it also. So apparently we are considering two different cases. And in your case the client to server path will not be probed by the client. Thus it become a question if the client needs to probe with a 1200+ packet or can rely on the ACKing of the servers PATH_RESPONSE padded to 1200+ for MTU verification?
The test-before-migrate is a MAY (Section 9.1) and Section 9.2 is pretty clear that a migration is initiated by sending non-probing frames and that a migrating endpoint can do that without first needing to validate the path.
I will note that the client is expected to a path validation with the server when it acts on the server preferred address: Section 9.6.1: URL A client might need to perform a connection migration before it has migrated to the server's preferred address. In this case, the client SHOULD perform path validation to both the original and preferred server address from the client's new address concurrently. So that case exist also here. The point is that we actually have two cases and both needs to be considered when discussing this.
Yes, that migration to the preferred address trips me up, because it reverses the path validation. I don't actually know if anyone has implemented this at all yet.
I think that this is remedied in the same way as we have elsewhere: we can recommend that endpoints pad probing packets to at least 1200 bytes. If any packet containing PATH_CHALLENGE is never less than 1200 bytes, the path will never be valid without the MTU also being sufficient. Rebinding will allow moving to path that is not validated, but I expect that not to be a significant risk. It seems equally likely that the path MTU would spontaneously reduce. And then there is the period where an unvalidated path is used, separate from the rebinding case. Nothing much to be done for that, but there is a firm limit on that, because a path is abandoned when validation fails.
NAME I'm not sure if I agree. I would write down the steps that I think would lead to a problem even when both endpoints pad their probe packets. Would you mind pointing out where I'm wrong? step 1: client sends a full-sized PATHCHALLENGE on a new path step 2: server receives that packet, sends a full-sized PATHRESPONSE on the old path step 3: client receives PATHRESPONSE, and calls the path as being validated step 4: (for some reason; e.g. client sending non-probe packets) server tries to validate the new path, by sending a full-sized PATHCHALLENGE on the new path step 5: client never receives the PATH_CHALLENGE because PMTU in the server -> client direction was sub-1200. step 6: server fails to validate the path
NAME were just discussing the same failure mode. Note also that the PATH_RESPONSE can be on the old path as well, so recommending padding for that won't work. I think that the padding idea is helpful, but not completely good. I'll explain more in a longer posting.
The reason that padding doesn't work is that the PATHRESPONSE can be small or follow a different path. At which point the client thinks that the path is good. If the client migrates, the server will attempt to validate that path. If the server pads to 1200, then its validation will fail. I think that the server switches back to the old path at this point, which might have no effect. The client might have closed the socket by then. At this point, the client continues in its use of the new, broken path. The server either keeps attempting to validate that new path successfully (at an interval determined by how often it retries path validation), or just gives up. If the server keeps going, you get into a weird state where the connection can stutter along. Either way, the connection is no longer useful. This is slightly faster than the case where PATHCHALLENGE is not padded in any way. There, you might end up with an path that appears to be good, until you need to send more data. That might take some time. At least this way you path validation failure within ~3PTO. Padding is also an improvement in that it detects paths that have an MTU that is uniformly less than 1200. Without revisiting the underlying design, I think that we just have to accept this limitation. And I guess we should acknowledge it - I'll add some text on that point.
I agree. I can't think of a way around the limitations here without redesigning the core design. I would suggest moving forward with padding PATH_CHALLENGEs and articulate the potential risks here. Connection migration remains a gift that keeps on giving, and I would expect it to give more as we experiment with it in the field. Let's not lose ourselves in trying to perfect the design of a feature that we are going to learn a lot more about as we deploy QUICv1.
+1 to not doing a redesign in v1. That said, I tend to think that it might be possible to fix this issue with small tweaks. Specifically, I wonder if stating following would address the problem: a sender MUST pad PATHCHALLENGE when receiving PATHCHALLENGE, an endpoint MUST send a padded PATHRESPONSE using the path on which PATHCHALLENGE was received receiving PATHRESPONSE on any path is valid (this is existing requirement) The reason we have the last bullet point is to prevent issues caused by MOTS attackers racing packets. We have to keep them. However, that necessary does not mean that the sender of PATHRESPONSE should be entitled to send PATHRESPONSE on any path. If we tighten the requirement on the sender of PATHRESPONSE, I think that the issue might go away, without causing any regression?
NAME I was literally writing exactly this out, modulo that last point, which I think is a very good addition. This is a small enough tweak even to the text that I think we can pull this off with a minor change. Specifically, the text that will need to change (in addition to requiring padding PATHRESPONSE) is: “A PATHRESPONSE frame does not need to be sent on the network path where the PATHCHALLENGE was received; a PATHRESPONSE can be sent on any network path.” We changed that when we changed validation to be unidirectional. We can retain that property of path validation, but still require PATHRESPONSE to be sent to the same address from which the PATHCHALLENGE was received.
I think NAME suggestion is sensible and simple enough. I will note that that second MUST is unenforceable given the third point, but I think that's ok.
Labeling this as "design" per
Simply note that I think the proposal in appear to be an okay resolution. I would recommend that people consider also so they are aligned.
LGTM, with a note regarding MUST vs. SHOULD for padding. As I pointed out in , datagram size is not authenticated, and therefore receivers can never enforce the use of padding (though they MAY discard packets that do not meet the padding requirement). If we go with a MUST, we should be clear about that.I think this is an improvement and is clear. So I am fine with going forward with this change.

Discussion:
frame so that it can associate the peer's response with the corresponding PATH_CHALLENGE. <ins> An endpoint MUST expand datagrams that contain a PATH_CHALLENGE frame to at least the smallest allowed maximum datagram size of 1200 bytes. Sending UDP datagrams of this size ensures that the network path from the endpoint to the peer can be used for QUIC; see datagram-size. </ins> 8.2.2. On receiving a PATH_CHALLENGE frame, an endpoint MUST respond by echoing the data contained in the PATH_CHALLENGE frame in a <del> PATH_RESPONSE frame.  A PATH_RESPONSE frame does not need to be sent on the network path where the PATH_CHALLENGE was received; a PATH_RESPONSE can be sent on any network path.  An endpoint MUST NOT delay transmission of a packet containing a PATH_RESPONSE frame unless constrained by congestion control. </del> <ins> PATH_RESPONSE frame.  An endpoint MUST NOT delay transmission of a packet containing a PATH_RESPONSE frame unless constrained by congestion control. A PATH_RESPONSE frame MUST be sent on the network path where the PATH_CHALLENGE was received.  This ensures that path validation by a peer only succeeds if the path is functional in both directions. This requirement MUST NOT be enforced by the endpoint that initiates path validation as that would enable an attack on migration; see off- path-forward. An endpoint MUST expand datagrams that contain a PATH_RESPONSE frame to at least the smallest allowed maximum datagram size of 1200 bytes. This verifies that the path is able to carry datagrams of this size in both directions. </ins> An endpoint MUST NOT send more than one PATH_RESPONSE frame in response to one PATH_CHALLENGE frame; see retransmission-of-

Path validation succeeds when a PATH_RESPONSE frame is received that contains the data that was sent in a previous PATH_CHALLENGE frame. <del> This validates the path on which the PATH_CHALLENGE was sent. </del> <ins> A PATH_RESPONSE frame received on any network path validates the path on which the PATH_CHALLENGE was sent. </ins> Receipt of an acknowledgment for a packet containing a PATH_CHALLENGE frame is not adequate validation, since the acknowledgment can be