Subject: [TLS] ESNIKeys.public_name vs. cleartext SNI

From: Stephen Farrell <[email-masked]>
Date: Sun, 28 Jul 2019 13:25:14 +0100

Hiya,

ESNI drafts -03 and -04 envisage that the ESNIKeys.public_name
and the TLS h/s cleartext SNI are the same. I'd expect that
they mostly will be.

But they don't have to be. A client could provide a way to
use a client-chosen cleartext SNI when using ESNI to encrypt
the real SNI.

For example, my openssl build allows this for s_client. I've
a colleague who's got a first build of curl using that that
also allows such a local over-ride. I think other command-line
clients might be likely to also support that kind of thing, if
for no other reason than the existence of the draft-02 version
that's deployed and has no public_name. But I guess being able
to do a local over-ride may also be generally useful, while
not being so useful for web browsers. For example, if a given
public_name value is being censored, clients might at that
point want to use something else.

On the server side, my code also make no checks that the
cleartext SNI used was the same as the public_name. And I
don't think that causes any problems, so maybe ought be
allowed too.

I don't think allowing this (if the WG decide to) requires
any major change to the spec, but there are a couple of
language changes needed in section 5.1.3 and I guess we
should add a sentence to the effect that using the public_name
value from ESNIKeys in the cleartext SNI is recommended
if you've no other value but is not required.

Cheers,
S.

---

From: Dmitry Belyavsky <[email-masked]>
Date: Sun, 28 Jul 2019 21:07:26 +0300

Dear Stephen,

I published a draft describing "Fake SNI" designed for the same purpose. It
allows (at least in theory) to cheat those who blocks all the handshakes
containing ESNI.

вс, 28 июля 2019 г., 15:25 Stephen Farrell <[email-masked]>:

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

---

From: Stephen Farrell <[email-masked]>
Date: Sun, 28 Jul 2019 20:05:25 +0100

Hiya,

> allows (at least in theory) to cheat those who blocks all the handshakes

Yes, I recall that. The question below was only really about
draft-ietf-tls-esni-04 though.

Cheers,
S.

>> ESNI drafts -03 and -04 envisage that the ESNIKeyublic_name

---

From: Christian Huitema <[email-masked]>
Date: Sun, 28 Jul 2019 17:32:00 -0700

> point want to use something else.

I see the intent, but I am not sure it is practical. A lot of the HTTP
connection establishment is automated. Given a server name, the client
will do a lookup for the ESNI record or a cached value. If there is one,
the simple solution is to put the public name in the SNI extension and
the actual name in the ESNI extension. If the public name is censored,
the solution is probably to look for a different ESNI record for the
server, one that would mention a different public name.

By the way, I think that the current ESNI record is maybe a little too
complicated. The ESNI key is really a property of the public server, yet
the ESNI record is defined as a property of the hidden server. If the
public server rolls a new key, all the ESNI records of all the hidden
servers that mentioned the old key need to be updated. I think it would
be simpler to have the ESNI record as a property of the public server,
and to just have a pointer to the public server in the context of the
hidden server. May an SRV record. The chain would be something like:

1) Look up whether the SRV record for _esni._tcp.hidden.example.com

2) If there are such records, select the appropriate public server, say
public.example.net

3) Look up ESNI, A, AAAA for public.example.net

In that architecture, there is no need to encode the public server name
in the ESNI record. I think there will be several advantages. The ESNI
record's TTL can be set to the lifetime of the key. The SRV record's TTL
can be set to the expected lifetime of the relation between 'hidden" and
"public". If the SRV lifetime is long enough, the value can be
efficiently cached by the client. If multiple clients share the same
hidden server, the ESNI record is fetched only once, and can be cached.
At connection time, the client would only need to query the A/AAAA
records of the public server, i.e. exactly the same DNS transaction as
an access to the public server.

-- Christian Huitema

---

From: Stephen Farrell <[email-masked]>
Date: Mon, 29 Jul 2019 12:12:16 +0100

Hiya,

On 29/07/2019 01:32, Christian Huitema wrote:
> I see the intent, but I am not sure it is practical. 

In which case I must've explained it badly, because it's
entirely practical:-) Let me try again...

What I'm asking is that we not insist that the cleartext
SNI is the ESNIKeys.public_name even though those will be
the same value in almost all cases.

I don't think there's any major security benefit to insisting
that they be the same and there are cases where e.g. a command
line tool like curl or wget can easily supply a different
cleartext SNI value as an override, should that ever be needed
or useful.

> A lot of the HTTP
> the actual name in the ESNI extension. 

Sure, I know that and am fine with it being the default.

> If the public name is censored,

If the public_name is censored, then there may be >1 solution
needed, so allowing for more than one seems better than assuming
there is one and only one solution in that circumstance.

> an access to the public server.

That seems a bit like the HTTPSSRV proposal and maybe better in
a different thread?

S.

---

From: Ben Schwartz <[email-masked]>
Date: Mon, 29 Jul 2019 09:35:21 -0400

> cleartext SNI value as an override, should that ever be needed

It sounds like you are arguing for replacing a MUST with a SHOULD.

I think our best option is probably to clarify who is supposed to do what,
and why.  For example, we could say that a compliant client MUST set sni =
public_name so that fallback can work on servers with multiple public
names, but the server MAY accept connections with missing or unrecognized
SNI to enable connections from non-compliant clients that prefer not to
include the public_name.

---

From: Stephen Farrell <[email-masked]>
Date: Mon, 29 Jul 2019 15:39:10 +0100

Hiya,

> It sounds like you are arguing for replacing a MUST with a SHOULD.

Sure, that'd be good enough, though I think a MAY is actually all
that's needed. I think the way I'd phrase it might be "clients
are advised to include the value of ESNIKeys.public_name in the
TLS handshake in the cleartext SNI extension; servers need to be
aware that some clients might not do so, either omitting cleartext
SNI entirely or including some other value that may or may not be
meaningful at that server; successful ESNI decryption means ignoring
any cleartext SNI value provided" and avoid use of 2119 terminology,
but I'm sure various possible wordings would be fine.

> names,  

I'm pretty sure I disagree with the above MUST as being necessary.

But what do you mean by "so that fallback can work"? ISTM that if
ESNI doesn't work, then the right thing is for the server to fail
or continue the TLS h/s based on the cleartext SNI as normal, or
to default to something if no cleartext SNI is provided, again as
normal. A client that's not only greasing MUST of course make it
appear to the client application that the TLS h/s failed, as ESNI
has failed.

> but the server MAY accept connections with missing or unrecognized

Right. I'd expect some variation in all this and would like that
we can make ESNI work even for clients with somewhat outdated or
incorrect information, if there's no security downside in so
doing.

Cheers,
S.

---

From: Ben Schwartz <[email-masked]>
Date: Mon, 29 Jul 2019 11:07:00 -0400

On Mon, Jul 29, 2019 at 10:39 AM Stephen Farrell <[email-masked]>
wrote:

> But what do you mean by "so that fallback can work"?

I mean "so that esni_retry_requested can work".  This is the ESNI fallback
mechanism, where the server delivers a fresh ESNIKeys in-band, and the
client closes the socket and tries again.  The client will only accept the
new ESNIKeys if the server's provided certificate validates for
public_name, but if the server has multiple public names, it will not in
general know which certificate to serve unless the client sets sni =
public_name.

Admittedly, having multiple public names in separate certificates may not
be a common case, but as long as we view it as in-scope, we have to require
sni = public_name for general-purpose clients.  Special-purpose clients
that have additional out-of-band information (like knowing that the server
only has one public name) are of course able to do whatever they want;
they're no longer tightly bound by the standard.

> ISTM that if

---

From: Stephen Farrell <[email-masked]>
Date: Mon, 29 Jul 2019 16:19:02 +0100

Hiya,

On 29/07/2019 16:07, Ben Schwartz wrote:
> 
> I mean "so that esni_retry_requested can work". 

Ah, gotcha. Fair point. Using public_name ought make this
much more likely to work if it's needed.

Ta,
S.

> This is the ESNI fallback