Subject: [dns-privacy] Use of 0-RTT in DNS over QUIC

From: Christian Huitema <[email-masked]>
Date: Thu, 29 Jul 2021 17:30:39 -0700

The DNS over QUIC draft lets client and server negotiate 0-RTT, with 
minimal guidance. The privacy section develops the risks of replay 
attacks, and then effectively lets clients decide whether to use 0-RTT 
or not. Martin Thomson pointed out the contrast with RFC 8470 which 
provides great details on the use of 0-RTT data in HTTP, and also 
introduces a new error code to let server refuse some transactions if 
received over 0-RTT. There are indeed advantages in letting the server 
control usage of 0-RTT, but I wonder about the proper trade-off between 
control and complexity for DoQ. There are multiple ways to do this:

- Allow servers to not advertise support for 0-RTT if they are concerned 
with 0-RTT side effects -- very simple to implement at servers and clients.

- Let servers advertise support for 0-RTT, but have them check the 
queries received on 0-RTT and return an error code after inspecting 
incoming requests. This requires implementing some kind of filter at the 
server side, plus some logic on the client to resubmit the failed 
requests after completion of the handshake. I am a bit concerned with 
that kind of complexity.

- Let servers advertise support for 0-RTT, but close the transaction 
with a Protocol Error if the server receives an unexpected request -- 
e.g., an Update. That also requires some filtering of 0-RTT packets at 
the server side, but is simpler than the full inspection considered 
above. It is also reasonably easy to implement on the client, which 
simply abstains to send some classes of requests over 0-RTT.

- Or, of course, allow servers to support 0-RTT without any kind of 
filtering.

Any particular opinion in the working group?

-- Christian Huitema

---

From: Ben Schwartz <[email-masked]>
Date: Fri, 30 Jul 2021 10:52:57 -0400

I think this should be decided as part of
https://datatracker.ietf.org/doc/html/draft-ietf-dprive-early-data, and DoQ
should just reference it.  (I don't necessarily agree with the present
contents of that draft.)

As for what draft-ietf-dprive-early-data should say, I don't have a strong
opinion.  However, I do think it's notable that most recursive resolvers
allow "cache probing" by setting RD=0 in the query, which enables a
relatively straightforward plaintext recovery attack on 0-RTT queries on
multi-instance recursive resolvers.  An attacker can probe a cache instance
until some records of interest fall out, then replay the 0-RTT query and
repeat the probes to see if any of them reappear.  As such, I think it
might be appropriate to strengthen the replay defense requirement for
encrypted DNS beyond the "SHOULD" in RFC 8446.

(See also https://github.com/tlswg/tls13-spec/issues/1225)

On Thu, Jul 29, 2021 at 8:31 PM Christian Huitema <[email-masked]>
wrote:

> _______________________________________________
> dns-privacy mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/dns-privacy
>

---

From: Robert Evans <[email-masked]>
Date: Fri, 30 Jul 2021 11:56:41 -0400

DoQ plus 0-RTT seems very compelling for achieving 1-RTT query/response
parity with Do53.

As such I think the spec should discuss 0-RTT and encourage both clients
and servers to support it.

I also think a recommended 0-RTT profile suitable for DoQ/T should be
developed and specified.

For example (but I'm not a TLS expert, corrections welcome):
- self-contained, non-single-use tickets
- ticket_lifetime at least 6 hours
- early_data allowed
- max_early_data_size of 512 bytes
- implement replay protection by freshness check
- reject ClientHello with age over 30 seconds
- offer tickets only on full handshakes or if ticket is old
- send tickets as early as possible in the session
- allow resumption for any SNI offered in the server certificate
- no early data for mutating queries

No opinion as to which draft should contain those recommendations.

On Fri, Jul 30, 2021 at 10:53 AM Ben Schwartz <bemasc=
[email-masked]> wrote:

> https://datatracker.ietf.org/doc/html/draft-ietf-dprive-early-data, and
> DoQ should just reference it.  (I don't necessarily agree with the present
> contents of that draft.)
>

---

From: Christian Huitema <[email-masked]>
Date: Fri, 30 Jul 2021 13:02:26 -0700

I think we have a reasonable guideline here. 0-RTT for QUIC is so 
compelling that clients and servers will still do it, even if we tell 
them not to. So it is better to try provide usage guidelines on how to 
do that safely.

Robert's proposal fall in two categories: some are about embracing 0-RTT 
in order to ensure good performance, like accepting early data and  
ensuring a minimum lifetime of tickets. (With some nits -- you cannot 
set the max_early_data_size to 512 bytes in QUIC, you have to use a QUIC 
transport parameter instead.) Then, some of the recommendations are 
about "try to keep it safe":

1) Do not accept a client hello that is older than 30 seconds. This 
would limit the efficacy of the replay attacks, because it probably 
takes at least 30 seconds to ensure that the cache is empty. But I am 
not too sure how one tests the lifetime of a client Hello.

2) Implement replay protection is a good idea. Some server deployments 
support that. But I understand that this kind of support ends up 
enforcing "only once" use of tickets. This contradicts the request for 
non-single-use tickets, or the request to "offer tickets only on full 
handshakes or if ticket is old".

Some QUIC stack will disable 0-RTT if the ticket is older than 30 
seconds, only allowing resumption. This is reasonably easy to implement.

-- Christian Huitema

---

From: Robert Evans <[email-masked]>
Date: Fri, 30 Jul 2021 16:38:10 -0400

On Fri, Jul 30, 2021 at 4:02 PM Christian Huitema <[email-masked]>
wrote:

> compelling that clients and servers will still do it, even if we tell them
> not to. So it is better to try provide usage guidelines on how to do that
> safely.
>
> ensuring a minimum lifetime of tickets. (With some nits -- you cannot set
> the max_early_data_size to 512 bytes in QUIC, you have to use a QUIC
> transport parameter instead.) Then, some of the recommendations are about
> "try to keep it safe":
>
> 1) Do not accept a client hello that is older than 30 seconds. This would
> limit the efficacy of the replay attacks, because it probably takes at
> least 30 seconds to ensure that the cache is empty. But I am not too sure
> how one tests the lifetime of a client Hello.
>
See https://datatracker.ietf.org/doc/html/rfc8446#section-8.3.

The idea is the ticket age from the client in conjunction with the ticket
issuance time is used to estimate the age of the ClientHello. I have no
idea if there's an equivalent in QUIC-TLS.

> support that. But I understand that this kind of support ends up enforcing
> "only once" use of tickets. This contradicts the request for non-single-use
> tickets, or the request to "offer tickets only on full handshakes or if
> ticket is old".
>
> Some QUIC stack will disable 0-RTT if the ticket is older than 30 seconds,
> only allowing resumption. This is reasonably easy to implement.
>
Single-use tickets, stateful replay protection, and limiting
session tickets to 30 seconds all bias against 0-RTT, hence we should draft
something which recommends avoiding all of those.

In other words, I think we should try to design DoQ to allow and recommend
deploying 0-RTT such that almost all queries can use 0-RTT after first
contact except in the long-tail case where the resolver almost never sends
queries.

> On Fri, Jul 30, 2021 at 10:53 AM Ben Schwartz <bemasc=[email-masked]> wrote:
>
>
> I think this should be decided as part ofhttps://datatracker.ietf.org/doc/html/draft-ietf-dprive-early-data, and
> On Thu, Jul 29, 2021 at 8:31 PM Christian Huitema <[email-masked]> <[email-masked]>
> wrote:
>
>
> dns-privacy mailing [email-masked]://www.ietf.org/mailman/listinfo/dns-privacy
>
> dns-privacy mailing [email-masked]://www.ietf.org/mailman/listinfo/dns-privacy
>
>
> dns-privacy mailing [email-masked]://www.ietf.org/mailman/listinfo/dns-privacy
>
>

---

From: Christian Huitema <[email-masked]>
Date: Fri, 30 Jul 2021 17:21:25 -0700

> See https://datatracker.ietf.org/doc/html/rfc8446#section-8.3.

I see. The proposed mechanism uses the obfuscated_ticket_age, from which 
the server can deduce the time at which the client sent the ClientHello. 
That's a good check for cooperating clients, but I do not think that it 
was designed to control replay attacks. The value is encoded by the 
client as the sum of the age of the ticket in milliseconds and the 
ticket_age_add parameter of the ticket. Attackers do not have access to 
the ticket_age_add value, but they do not need to. They merely need to 
increment the obfuscated_ticket_age by the delay in milliseconds between 
capture and replay. I would not recommend relying on that mechanism as a 
defense against cache probing attacks.

> something which recommends avoiding all of those.

Single use tickets are not a problem if the ticket is renewed after use. 
We are concerned with replay attacks, but in the case of a replay attack 
the handshake does not conclude correctly. Renewing a ticket after the 
handshakes concludes correctly should work in most cases. Note that we 
are bound to recommend single use tickets anyhow, because the ticket is 
a unique identifier of the client and reusing it enables tracking.

I understand your concern about limiting 0-RTT capability to a short 
duration. I am just looking for alternatives that can easily be 
implemented in multiple stacks. If something like the 
obfuscated_ticket_age mechanism was robust against replays, it would 
work. But as it is, I don't think it does.

> contact except in the long-tail case where the resolver almost never sends

I agree with that goal. But I would like a mechanism by which servers 
can reliably prevent replay attacks.

-- Christian Huitema

---

From: Benjamin Kaduk <[email-masked]>
Date: Fri, 30 Jul 2021 17:33:01 -0700

On Fri, Jul 30, 2021 at 05:21:25PM -0700, Christian Huitema wrote:
> > See https://urldefense.com/v3/__https://datatracker.ietf.org/doc/html/rfc8446*section-8.3__;Iw!!GjvTz_vk!FuZeymeFKUmTSm947f29K29rPi_MMwIRxbdCaDFCCXrRX-J4CThQ7Yx3aAvg4g$ .
> 
> I see. The proposed mechanism uses the obfuscated_ticket_age, from which the
> server can deduce the time at which the client sent the ClientHello. That's
> a good check for cooperating clients, but I do not think that it was
> designed to control replay attacks. The value is encoded by the client as
> the sum of the age of the ticket in milliseconds and the ticket_age_add
> parameter of the ticket. Attackers do not have access to the ticket_age_add
> value, but they do not need to. They merely need to increment the
> obfuscated_ticket_age by the delay in milliseconds between capture and
> replay. I would not recommend relying on that mechanism as a defense against
> cache probing attacks.

Wouldn't that break the PSK binder?

-Ben

---

From: Christian Huitema <[email-masked]>
Date: Fri, 30 Jul 2021 17:53:11 -0700

On 7/30/2021 5:33 PM, Benjamin Kaduk wrote:
>>> On Fri, Jul 30, 2021 at 4:02 PM Christian Huitema<[email-masked]>
>>> wrote:
>>>
>>> Seehttps://urldefense.com/v3/__https://datatracker.ietf.org/doc/html/rfc8446*section-8.3__;Iw!!GjvTz_vk!FuZeymeFKUmTSm947f29K29rPi_MMwIRxbdCaDFCCXrRX-J4CThQ7Yx3aAvg4g$  .

Yes it would, of course. And that would indeed prevent replaying the 
0-RTT data. I was wrong.

-- Christian Huitema