Subject: [quicwg/base-drafts] Defend against endless Stateless Reset ping-pong (#1627)

From: Martin Thomson <[email-masked]>
Date: Wed, 01 Aug 2018 00:05:13 -0700

This implements the agreed defenses, giving implementations a suite of
choices.  None of these a non-deterministic, as agreed.

Closes #1443.
You can view, comment on, or merge this pull request online at:

  https://github.com/quicwg/base-drafts/pull/1627

-- Commit Summary --

  * Defend against endless Stateless Reset ping-pong

-- File Changes --

    M draft-ietf-quic-transport.md (41)

-- Patch Links --

https://github.com/quicwg/base-drafts/pull/1627.patch
https://github.com/quicwg/base-drafts/pull/1627.diff

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627

---

From: Marten Seemann <[email-masked]>
Date: Wed, 01 Aug 2018 00:14:16 -0700

marten-seemann commented on this pull request.

> +#### Looping {#reset-looping}
+
+The design of a Stateless Reset is such that it is indistinguishable from a
+valid packet.  This means that a Stateless Reset might trigger the sending of a
+Stateless Reset in response, which could lead to infinite exchanges.  An
+endpoint MUST use any one of the following measures to limit the sending of
+Stateless Reset:
+
+* An endpoint can remember the number of Stateless Reset packets that it has
+  sent and stop generating new Stateless Reset packets once a limit is reached.
+  Using separate limits for different remote addresses will ensure that
+  Stateless Reset packets can be used for some peers even when other peers have
+  exhausted limits.
+
+* An endpoint can set the TTL in the IP header to one fewer than the TTL in the
+  packet that it received.  Once the TTL reaches zero, any looping ends.

This only works if both endpoints do this, right?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627#pullrequestreview-142251700

---

From: Marten Seemann <[email-masked]>
Date: Wed, 01 Aug 2018 00:17:00 -0700

> +Note that Stateless Reset packets do not have any cryptographic protection.
+
+

I'm not sure if we discussed this anywhere, but if you're willing to keep some state around for a short period of time, wouldn't the easiest thing be to save the last 16 bytes of the packet (for each remote address), and if they match on two (non-identical) packets, you can be pretty sure that those are Stateless Resets.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627#pullrequestreview-142252403

---

From: Kazuho Oku <[email-masked]>
Date: Wed, 01 Aug 2018 00:18:03 -0700

kazuho commented on this pull request.

> @@ -2669,7 +2671,36 @@ the same static key (see {{reset-oracle}}).  A connection ID from a connection
 that is reset by revealing the Stateless Reset Token cannot be reused for new
 connections at nodes that share a static key.
 
-Note that Stateless Reset messages do not have any cryptographic protection.

Would it make sense to suggest "using separate limits" for different DCIDs of the incoming packets in addition to "remote addresses"?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627#pullrequestreview-142252667

---

From: Martin Thomson <[email-masked]>
Date: Wed, 01 Aug 2018 00:25:41 -0700

martinthomson commented on this pull request.

+
+

If they use the technique we describe, the input to the calculation for a stateless reset is the connection ID from the inbound packet - and that is randomized in a stateless reset.  So no winner there.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627#discussion_r206778353

---

From: Martin Thomson <[email-masked]>
Date: Wed, 01 Aug 2018 00:26:22 -0700

Further segregating by destination connection ID might work, yes.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627#discussion_r206778521

---

From: Martin Thomson <[email-masked]>
Date: Wed, 01 Aug 2018 00:28:11 -0700

@martinthomson pushed 1 commit.

1c9a56a  Segregate on DCID too

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627/files/80e17eed41c1f04314575120ba3bb437d508d74d..1c9a56ab12908c13e44c93855702729133b7c130

---

From: Martin Thomson <[email-masked]>
Date: Wed, 01 Aug 2018 00:31:01 -0700

+

Yeah, it would also work if the Stateless Reset were the same size as the triggering packet (on the assumption that the peer is applying one of the other techniques), but that's pretty marginal, so I'm going to cut this option.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627#discussion_r206779601

---

From: Martin Thomson <[email-masked]>
Date: Wed, 01 Aug 2018 00:33:06 -0700

dabfda7  Reword a little, cut the TTL thing, which only works in a homogeneous environment

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627/files/1c9a56ab12908c13e44c93855702729133b7c130..dabfda789abdec2c4e1a040e160e12d8b131aed0

---

From: Dmitri Tikhonov <[email-masked]>
Date: Wed, 01 Aug 2018 06:02:47 -0700

dtikhonov commented on this pull request.

> @@ -2596,10 +2597,11 @@ Using a randomized connection ID results in two problems:
 
 * The packet might not reach the peer.  If the Destination Connection ID is
   critical for routing toward the peer, then this packet could be incorrectly
-  routed.  This causes the stateless reset to be ineffective in causing errors
-  to be quickly detected and recovered.  In this case, endpoints will need to
-  rely on other methods - such as timers - to detect that the connection has
-  failed.
+  routed.  This might also triggering another Stateless Reset in response, see

s/triggering/trigger/ ?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627#pullrequestreview-142364075

---

From: Martin Thomson <[email-masked]>
Date: Wed, 01 Aug 2018 16:53:08 -0700

698f42b  --ing

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627/files/dabfda789abdec2c4e1a040e160e12d8b131aed0..698f42b8c74924fa69264318829b160793dfac12

---

From: ianswett <[email-masked]>
Date: Wed, 01 Aug 2018 17:29:11 -0700

ianswett commented on this pull request.

+
+The design of a Stateless Reset is such that it is indistinguishable from a
+valid packet.  This means that a Stateless Reset might trigger the sending of a
+Stateless Reset in response, which could lead to infinite exchanges.  An
+endpoint MUST use any one of the following measures to limit the sending of
+Stateless Reset:
+
+* An endpoint can remember the number of Stateless Reset packets that it has
+  sent and stop generating new Stateless Reset packets once a limit is reached.
+  Using separate limits for different remote addresses - or different values for
+  the Destination Connection ID fields on the packet that triggers the reset -
+  will ensure that Stateless Reset packets can be used to close connections when
+  other peers or connections have exhausted limits.
+
+* An endpoint can ensure that every Stateless Reset that it sends is smaller

I think it's worth advising that a stateless reset should never be larger than the received packet.  This makes this defense unilaterally useful, because at least one side is reducing the size every time.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627#pullrequestreview-142609921

---

From: Martin Thomson <[email-masked]>
Date: Wed, 01 Aug 2018 17:31:18 -0700

+

That's a good point, and a reason that the TTL defense was removed.  I will restructure.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627#discussion_r207071737

---

From: Martin Thomson <[email-masked]>
Date: Wed, 01 Aug 2018 17:37:59 -0700

+

On second thought: if one peer is remembering, then the problem does eventually go away without size reductions.  But it requires that the state is not bound to a connection ID (as @kazuho suggested), it has to be bound to a remote address.

I have restructed the text to emphasize size reduction as the first defense.   State is then an alternative.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627#discussion_r207072528

---

From: Martin Thomson <[email-masked]>
Date: Wed, 01 Aug 2018 17:38:26 -0700

8e86b2a  Emphasize size reductions as the primary defense, restructure

-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627/files/698f42b8c74924fa69264318829b160793dfac12..8e86b2a2c9004f43a8711b73b718bfde584f0d1d

---

From: ianswett <[email-masked]>
Date: Wed, 01 Aug 2018 17:47:31 -0700

ianswett approved this pull request.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627#pullrequestreview-142612430

---

From: Martin Thomson <[email-masked]>
Date: Sun, 05 Aug 2018 22:44:12 -0700

Merged #1627 into master.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/1627#event-1772040659