Agreed. I'm proposing we require either not resetting(under the assumption the path hasn't meaningfully changed) or applying the 3x limit, but not both. This might be a result of Martin's current PR, but if so we should probably make the point and the reasoning more explicit.
On Wed, Oct 28, 2020 at 4:28 PM Martin Duke <[email protected]> wrote: > NAT doesn't require reset, but there are times when it's wise, > particularly when the NAT is closer to the server than the client. (e.g. a > NAT might signal a mobility event on the clientside by changing its port) > > On Wed, Oct 28, 2020 at 1:04 PM Ian Swett <ianswett= > [email protected]> wrote: > >> I'll note that this problem is created/worsened by the fact that the >> congestion controller is reset. If it was not reset, you'd be limited by >> the existing congestion controller. >> >> That would allow you to build up a big window and direct it at another >> path, but creating a larger window is more work on top of completing the >> handshake. >> >> NAT rebinds don't require resetting the congestion controller if my >> memory is correct, so I don't believe they don't need to be covered by this >> new amplification factor. >> >> Ian >> >> On Wed, Oct 28, 2020 at 2:18 AM Mikkel Fahnøe Jørgensen < >> [email protected]> wrote: >> >>> Rather than a race to the top with padding, would it be possible to do >>> the opposite: >>> >>> Force challenges and responses to occur in their packets and also UDP >>> datagrams. This prevents other traffic until a path is confirmed. >>> >>> The initial handshake has several concerns with padding: >>> >>> - amplification attack mitigation >>> - PMTU discovery >>> - reply capacity for completing handshake >>> >>> Since new paths do not need a handshake, there is less need for large >>> replies. Of course there is the PMTU issue still. >>> >>> >>> >>> Kind Regards, >>> Mikkel Fahnøe Jørgensen >>> >>> >>> On 28 October 2020 at 03.55.46, Eric Kinnear ( >>> [email protected]) wrote: >>> >>> This is an interesting PR, and likely accomplishes the goals at the >>> moment. >>> I do really like how we’ve kept some bidirectionally of the approach and >>> the padding can stay as is. >>> >>> Just thinking things through a little bit: >>> (This is all discussed below by Ian/Magnus/Martin/Kazuho, and others, >>> just restating so we have it in one place) >>> >>> At any point, either endpoint can choose to send a PATH_CHALLENGE. >>> The presence of a PATH_CHALLENGE always evokes a PATH_RESPONSE. >>> >>> Therefore, we assume that in order to restrict folks from being able to >>> spoof a source address when sending a PATH_CHALLENGE and attack the real >>> owner of that source address with the PATH_RESPONSE, we need to make the >>> PATH_CHALLENGE very large as well. >>> >>> However, there’s another situation where PATH_CHALLENGE is sent, and >>> that's whenever we receive a non-probing packet that arrives on a new path >>> without any prior validation, and we send that PATH_CHALLENGE on both the >>> old and the new path. >>> >>> This is where we haven’t fully plugged the amplification hole, since an >>> attacker can use *any other, smaller datagram* to cause the other >>> endpoint to generate full-size datagrams containing PATH_CHALLENGE. This >>> wasn’t previously a huge issue since PATH_CHALLENGE wasn’t meaningfully >>> larger than the smallest packet you’d otherwise be able to send (slash the >>> per-packet costs were potentially higher than the cost of the data inside >>> that packet). >>> >>> ——— >>> >>> One other approach we could take here would be to restrict ourselves to >>> only covering the cases where you’re actively generating a PATH_CHALLENGE >>> to validate a new path, not responding to a new non-probing packet on an >>> unvalidated path. >>> >>> In other words: >>> Only the client needs to pad PATH_CHALLENGE and any response to a padded >>> PATH_CHALLENGE should also be padded. That also fits nicely into the >>> unidirectionality of path validation as it stands today. >>> >>> >>> The other option that we haven’t discussed much is if we’d rather live >>> with the previous pre-padding problem and remove the padding. >>> My initial inclination was to avoid this, but actually we’d be returning >>> to a state where the main risk was that the path wasn’t MTU compatible and >>> any implementation migrating is likely already dealing with cases where >>> packets aren’t going through on a path in at least one direction. So, the >>> natural responses to path validation failures (for MTU reasons or >>> otherwise), if you map them all out, generally result in the “correct” >>> behavior. We could then say “any endpoint using a new path is encouraged to >>> do PMTUD or otherwise be careful that the path may not work in at least one >>> direction” and leave it at that. >>> >>> ——— >>> >>> Overall, I suspect we’re probably headed in the right direction by >>> making the 3x limit more universal, although it does seem like it >>> introduces some really interesting cases to code around, and that limit and >>> double path validation might be more painful than just checking for “am I >>> client, therefore I should pad” which is annoying because it has a >>> client/server distinction but does likely cause less churn and risk for >>> later fallout. >>> >>> Thanks, >>> Eric >>> >>> >>> On Oct 27, 2020, at 7:41 PM, Martin Thomson <[email protected]> wrote: >>> >>> Thanks to everyone for the feedback. >>> >>> I've written up a draft pull request here: >>> https://github.com/quicwg/base-drafts/pull/4264 >>> >>> This does something like what Magnus suggests below. It's not pretty, >>> because in some very common cases path validation could take twice as long, >>> and it's more complicated, but I think that it is at least principled. >>> >>> On Wed, Oct 28, 2020, at 04:04, Magnus Westerlund wrote: >>> >>> On Tue, 2020-10-27 at 09:12 -0400, Ian Swett wrote: >>> >>> Thanks for summarizing this issue. I think the above discussion is about >>> immediate migration and repeated immediate migrations, but I also wonder >>> if >>> we've introduced a single packet amplification attack by requiring >>> PATH_RESPONSEs be padded on new paths without a requirement on the size >>> of >>> PATH_CHALLENGE(see first item)? >>> >>> Validating a new path >>> If one receives only a PATH_CHALLENGE on a new path, then the server >>> responds with a full-sized PATH_RESPONSE. This seems safe. If a >>> non-padded >>> PATH_CHALLENGE is received on a new path, then the peer is supposed to >>> send a >>> fully padded PATH_RESPONSE on the path, which could be >20x larger. I'm >>> not >>> sure if we care about this, but I wanted to point it out. >>> >>> Immediately migrating to a new path >>> I think we should remove the text about allowing kMinimumWindow each >>> kInitialRtt after migration and change it to the 3x limit. I'm actually >>> surprised the text about 2*kInitialWindow still exists, since recovery >>> says >>> "Until the server has validated the client's address on the path, the >>> amount >>> of data it can send is limited to three times the amount of data >>> received, as >>> specified in Section 8.1 of {{QUIC-TRANSPORT}}.". >>> >>> In order to not get deadlocked by the 3x factor, I think we should >>> change the >>> newly added MUSTs to only apply to path validation prior to migration, >>> not the >>> peer responding to migration. >>> >>> My reasoning is that if a peer migrates prior to validating the path, it >>> means >>> it's either unintentional or they have no other choice, so the migrating >>> peer >>> has implicitly decided that validating PathMTU is not a prerequisite to >>> migrating. >>> >>> >>> So some quesitons and ideas as I think it is relevant to resolve this as >>> best as >>> possible. >>> >>> So isn't this recreating the issue that if the client initiates a >>> migration to a >>> new path that is not QUIC compatible, by responding with a minimal size >>> packet >>> and completing the migration and then if the server performs the path >>> verification with 1200 bytes UDP payload it fails. Thus maintaining a >>> broken >>> path. >>> >>> So is there need for the non pre-validated path migration case that one >>> need >>> need to do a two step process where one will ACK with minimal packet >>> while >>> initiating path validation. If path validatation fails then maybe one >>> need to >>> close down the connection as the migration ended up on a path that was >>> unable to >>> support QUIC. The question here is how to avoid the DoS attack this may >>> open up >>> if an attack rewrites source address of packets. >>> >>> So Maybe the path validation needs to be a two step process. First a >>> return >>> routability over the new path to verify that it is bi-directional. When >>> that has >>> been verified one does a test with minimal MTU to prove it to be QUIC >>> compatible. This might even be done with application data if there is >>> some that >>> are available to send. >>> >>> But, I think that one needs to work through the criterias for when the >>> QUIC >>> connection is shut down under the conditions that the path available is >>> not >>> supporting 1200 bytes. Also do we end up in a situation where the client >>> needs >>> to do the second step itself towards the server to verify the path so >>> that it >>> can determine if it needs to try another path if this one doesn't work? >>> >>> Cheers >>> >>> Magnus >>> >>> >>> Attachments: >>> * smime.p7s >>> >>> >>> >>>
