Subject: [TLS] publishing ESNIKeys under a .well-known URI...

From: Stephen Farrell <[email-masked]>
Date: Wed, 26 Jun 2019 11:20:50 +0100

Hiya,

I'm wondering if a thing I did when setting up a web
server with ESNI might be generally useful for some, but
not all, implementers.

My web server doesn't have an API it can use to update
ESNIKeys in the DNS. Many implementations/deployments may
have such an API but in my case, the zone file that
includes the ESNIKeys RR is on another machine and the
web server doesn't have write access to that. I do
control both machines as it happens, but I still don't
want to give general write-access to the web server.

So what I did was create a .well-known URI on the web
server that allows our "zone factory" to poll for changes
to ESNIKeys RRs. In my case I have the web server
generate new ESNIKeys each hour and publish those at
.well-known URIs; the "zone factory" polls for those
(also hourly) and when it sees new values, it checks that
those work, and if they do it updates the zone file and
re-publishes (DNSSEC signing, sending to hidden master
etc.) There are some more details below that could easily
change if we wanted to standardare this.

Anyway it all seems to work ok and could be useful for
others in a similar situation, or for web server
implementers as a generic way to make ESNIKeys available,
so I'm wondering if this'd be a useful PR for the ESNI
I-D, or if a separate I-D would be useful, or maybe not
enough people would need to do this to bother?

Cheers,
S.

Details:

- Web server generates new ESNIKeys hourly at N past
  the hour via a cronjob
- ESNIKeys are "current" for an hour, and published with
  a TTL of 1800 for no particularly good reason
- Old ESNIKeys are still usable for 3 hours, again for no
  particular reason (just 2 should do:-)
- Web server has a set of "hidden" sites ($HIDDEN) and a
  "cover" site ($COVER)
- The cronjob creates creates a JSON file for each hidden
  site at https://$COVER/.well-known/esni/$HIDDEN.json
- Each JSON file contains an array with the ESNIKeys RR
  values for that particular $HIDDEN as shown below:

    [
        {
            "ESNIKeys.version": 0xff01,
            "desired-ttl": 1800,
            "ESNIKeys": "/wH5QHc...="
        },
        {
            "ESNIKeys.version": 0xff02,
            "desired-ttl": 1800,
            "ESNIKeys": "FF02897...OA"
        }
    ]

- The specifics of the JSON structure are just what was
  handy for me, I'm sure it could be better, and would
  change as we go if we standardise this
- The values above with ellipses are the RR values we
  want to eventually see in the DNS
- On the zone factory, a cronjob runs at N+3 past the
  hour, it knows all the names involved and checks to see
  if the content at those well-known URIs has changed or
  not
- If the content has changed the cron job attempts to use
  the ESNIKeys and for each $HIDDEN where that works, it
  updates the zone file and re-publishes
- Possibly interesting unintended consequence: after a
  TLS client had first gotten ESNIKeys from the DNS for
  $HIDDEN with the draft-03 ESNIKeys structure containing
  the public_name field, the TLS client would know both
  $COVER and $HIDDEN and so could later probe for this
  .well-known as an alternative to doing so via DoT/DoH.
  Probably not something a web browser might do, but
  could be fun for other applications maybe

---

From: Michael Richardson <[email-masked]>
Date: Wed, 26 Jun 2019 11:58:09 -0400

> want to give general write-access to the web server.

When you say, "general write-access", did you mean that you didn't want to
setup Dynamic DNS to be able to update the QNAMEs involved, because that
usually permits the web server to delete A and AAAA records, as well as
updating the ESNI ?

Or did you mean "general write-access", meaning NFS or something like that?

--
Michael Richardson <[email-masked]>, Sandelman Software Works
 -= IPv6 IoT consulting =-

---

From: Stephen Farrell <[email-masked]>
Date: Wed, 26 Jun 2019 17:11:51 +0100

Hiya,

> Or did you mean "general write-access", meaning NFS or something like that?

Both really. NFS, or scripting up something with ssh,
would be easy but isn't desirable for local reasons.
DDNS seemed like more work, (but I didn't check it out
in detail tbh), wouldn't be otherwise useful in my
setup, and yes would need an authorisation model that
doesn't exist at the moment in our setup.

Like I said, what I did won't be needed everywhere, but
maybe it's useful enough to document properly and/or
standardise, not sure.

Cheers,
S.

---

From: Christian Huitema <[email-masked]>
Date: Wed, 26 Jun 2019 10:13:08 -0700

> maybe it's useful enough to document properly and/or

I think Stephen's issue will be quite common, especially for small
sites. I may be wrong, but it is quite common for small sites to use a
DNS provider's management UI to update DNS data. This will create a
de-facto limit on how often they can update the ESNIKeys RR, and thus
the key itself.

But then, we should ask how often these sites need to update the ESNI
key. I understand one part of the threat model, that attackers can use
an old compromised private key to break the privacy of clients using the
old public key, hence the need to refresh the keys reasonably often. But
there is a flip side of that. If the TTL of the ESNI record is small,
clients will need frequent DNS interactions to refresh it, and their
privacy could also be compromised during these operations. So, there are
two threats: compromised keys on one side, observable DNS transactions
on the other side. How do we navigate between these two threats?

-- Christian Huitema