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
>>>
>>>
>>>
>>>

Reply via email to