Draft: draft-ietf-tls-esni

Commentary: Try 2 . This turned out to be somewhat tricky due to existing text using " ESNI record " and " ESNIKeys record " ( and similar ) interchangeably , so I might have missed some instances . An alternative design would have been to have a single ESNIRecord value per ESNI record , and then have multiple ESNIKeys values for each ESNIRecord ( instead of multiple ESNIRecord values per ESNI and single    ) , though that will require more changes . 
 Thanks , 
 Filing this so we do n't forget : Currently the record digest covers the address_set extension . This means adding a new addresses to a deployment introduces new digests that need to be propagated to all servers to recognize . ( Unless servers trial decrypt everything , but then record digests are n't doing anything . ) Perhaps the A / AAAA + ESNI gluing should external to the ESNIKeys structure . The glue is probably assembled by DNS serving logic , while ESNIKeys is otherwise probably an opaque blob assembled by some key provisioning system . 
 Made to try to address this by excluding extensions from the digest . A DNS server that knows it will generate extensions can keep the rest of ESNIKeys as blob , and then simply append extensions to it when serving the record . Otherwise I would n't know where to put the AddressSet thingy . 
 What do you think about splitting it in two layers ? First you 've got ESNIKeys as it existed prior to address_set . The record digest covers the whole thing as before . DNS believes it 's just an opaque blob . Then you 've got , say , some BUNDLE RRTYPE whose RDATA encodes a list of ( RRTYPE , RDATA ) tuples in whatever DNS - y syntax people want . The DNS server then just assembles a BUNDLE with A and AAAA formatted as before , plus an ESNI record with it . This avoids this odd situation we have here where ESNI wants to be the root of the tree , to the exclusion of everyone else who may wish to correlate data with A / AAAA . A nuisance here : we do want to avoid the client having to ask for all of A , AAAA , ESNI , and BUNDLE . It is more risk of performance problems and acting on any response to ESNI would reintroduce multi - CDN woes . We 'd have to say ESNI can only be fetched via BUNDLE or so . ( That perhaps suggests the " keys " in BUNDLE should be its own namespace ? Other than A / AAAA , everything else is likely to never be fetched on its own . ) 
 I agree that the problem is really in DNS , and a complete solution needs to happen there . However I think it 's orthogonal to ESNI , and should probably be discussed on its own ( e.g. in dnsop ) . There was some talk in Prague about doing that but AFAICT nothing happened yet , so I 'd be interested in helping put a BUNDLE proposal together if nothing else comes up , and see what the DNS people think . In the meantime AddressSet is what we have , and it 's probably easier to just make that work for the specific ESNI case in the short term , and then replace it with whatever BUNDLE solution comes out later on , so the two discussions can proceed in parallel . 
 Well , we do n't have anything right now because address_set does n't work . :-P We can change the syntax however we like , be it defining BUNDLE in the ESNI doc , or doing something quick and hacky like : 
 My +1 goes to doing this hack , assuming that it helps somebody deploying ESNI . If it turns out to be a bad idea , we can switch to a different mechanism by just bumping the version number in ESNIKeys . 
 yeah , so that 's similar to proposal of just having an additional extensions field that does n't go into recorddigest . The additional extensions field would be somewhat more flexible and accomodate both addressset and the other multi - CDN proposal if it ever shows up . Do we care about this flexibility ? I find both solutions kinda yucky , but I guess those are the options we have . I can update my PR ( or create a new one ) with whatever new hack . 
 Actually , I do n't know if the other multi - CDN proposal would have the same problem , so maybe the extensibility is not needed ? 
 How about : We can then put addressset in dnsextensions , and TLS stacks do n't ever have to see them . 
 Yeah , was thinking something along those lines , I 'll see if I can put it into text in the next few days if nobody beats me to it .
Paragraph (version A):
Publishing ESNI keys in the DNS requires care to ensure correct
behavior.  There are deployment environments in which a domain is
served by multiple server operators who do not manage the ESNI Keys.
Because ESNIKeys and A/AAAA lookup are independent, it is therefore
possible to obtain an ESNIKeys record which does not match the A/AAAA
records.  (That is, the host to which an A or AAAA record refers is
not in possession of the ESNI keys.)  The design of the system must
therefore allow clients to detect and recover from this situation.
Paragraph (version B):
Publishing ESNI keys in the DNS requires care to ensure correct
behavior.  There are deployment environments in which a domain is
served by multiple server operators who do not manage the ESNI keys.
Because ESNI and A/AAAA lookups are independent, it is therefore
possible to obtain an ESNI record which does not match the A/AAAA
records.  (That is, the host to which an A or AAAA record refers is
not in possession of the ESNI keys.)  The design of the system must
therefore allow clients to detect and recover from this situation
(see esni-resolution for more details).
Paragraph (version A):
SNI Encryption keys can be published using the following ESNIKeys
structure.
Paragraph (version B):
SNI Encryption keys can be published using the following ESNIRecord
structure.
Paragraph (version B):
An ESNIKeys structure that contains the actual keys used to
encrypt the SNI as well as some metadata related to those keys.
Paragraph (version B):
A list of extensions that the client can take into consideration
when resolving the target DNS name.  The format is defined in
RFC8446; Section 4.2.  The purpose of the field is to provide room
for additional features in the future.  An extension may be tagged
as mandatory by using an extension type codepoint with the high
order bit set to 1.  A client which receives a mandatory extension
they do not understand must reject the ESNIRecord values.
Paragraph (version A):
padded_length : The length to pad the ServerNameList value to prior
to encryption.  This value SHOULD be set to the largest
ServerNameList the server expects to support rounded up the nearest
multiple of 16.  If the server supports wildcard names, it SHOULD set
this value to 260.
Paragraph (version B):
padded_length The length to pad the ServerNameList value to prior to
encryption.  This value SHOULD be set to the largest ServerNameList
the server expects to support rounded up the nearest multiple of 16.
If the server supports wildcard names, it SHOULD set this value to
260.
Paragraph (version A):
A list of extensions that the client can take into consideration
when generating a Client Hello message.  The format is defined in
RFC8446; Section 4.2.  The purpose of the field is to provide room
for additional features in the future.  An extension may be tagged
as mandatory by using an extension type codepoint with the high
order bit set to 1.  A client which receives a mandatory extension
they do not understand must reject the record.
Paragraph (version A):
The semantics of this structure are simple: any of the listed keys
may be used to encrypt the SNI for the associated domain name.  The
cipher suite list is orthogonal to the list of keys, so each key may
be used with any cipher suite.  Clients MUST parse the extension list
and check for unsupported mandatory extensions.  If an unsupported
mandatory extension is present, clients MUST reject the ESNIKeys
record.
Paragraph (version A):
This structure is placed in the RRData section of an ESNI record as-
is.  Servers MAY supply multiple ESNIKeys values, either of the same
or of different versions.  This allows a server to support multiple
versions at once.  If the server does not supply any ESNIKeys values
with a version known to the client, then the client MUST behave as if
no ESNIKeys were found.
Paragraph (version B):
A list of extensions that the client can take into consideration
when generating a Client Hello message.  The format is defined in
RFC8446; Section 4.2.  The purpose of the field is to provide room
for additional features in the future.  An extension may be tagged
as mandatory by using an extension type codepoint with the high
order bit set to 1.  A client which receives a mandatory extension
they do not understand must reject the ESNIRecord value.
Paragraph (version B):
Any of the listed keys in the ESNIKeys value may be used to encrypt
the SNI for the associated domain name.  The cipher suite list is
orthogonal to the list of keys, so each key may be used with any
cipher suite.  Clients MUST parse the extension list and check for
unsupported mandatory extensions.  If an unsupported mandatory
extension is present, clients MUST reject the ESNIRecord value.
Paragraph (version B):
The ESNIRecord structure is placed in the RRData section of an ESNI
record as-is.  Servers MAY supply multiple ESNIRecord values, with
ESNIKeys either of the same or of different versions.  This allows a
server to support multiple versions at once.  If the server does not
supply any ESNIRecord values with an ESNIKeys version known to the
client, then the client MUST behave as if no ESNI records were found.
Paragraph (version A):
"not_before" and "not_after" fields represent the validity period of
the published ESNI keys.  Clients MUST NOT use ESNI keys that was
covered by an invalid checksum or beyond the published period.  If
none of the ESNI keys values are acceptable, the client SHOULD behave
as if no ESNIKeys were found.
Paragraph (version B):
"not_before" and "not_after" fields represent the validity period of
the published ESNI keys.  Clients MUST NOT use ESNI keys that was
covered by an invalid checksum or beyond the published period.  If
none of the ESNI keys values are acceptable, the client SHOULD behave
as if no ESNI records were found.
Paragraph (version A):
Client MAY cache the ESNIKeys for a particular domain based on the
TTL of the Resource Record, but SHOULD NOT cache it based on the
not_after value, to allow servers to rotate the keys often and
improve forward secrecy.
Paragraph (version A):
Note that the length of this structure MUST NOT exceed 2^16 - 1, as
the RDLENGTH is only 16 bits RFC1035.
Paragraph (version A):
This section describes a client ESNI resolution algorithm using a new
"address_set" extension described below.  Future specifications may
introduce new extensions and corresponding resolution algorithms.
Paragraph (version B):
Client MAY cache the ESNIRecord values for a particular domain based
on the TTL of the Resource Record, but SHOULD NOT cache them based on
the not_after value of the ESNIKeys structure, to allow servers to
rotate the keys often and improve forward secrecy.
Paragraph (version B):
Note that the length of the ESNIRecord structure MUST NOT exceed 2^16
- 1, as the RDLENGTH is only 16 bits RFC1035.
Paragraph (version B):
This section describes a client ESNI resolution algorithm using an
"address_set" extension for the ESNIRecord structure.  Future
specifications may introduce new ESNIRecord extensions and
corresponding resolution algorithms.
Paragraph (version B):
This extension MUST NOT be placed in the ESNIKeys extensions field,
but only in the ESNIRecord dns_extensions field.
Paragraph (version A):
Clients SHOULD initiate ESNI queries in parallel alongside normal A
or AAAA queries to obtain address information in a timely manner in
the event that ESNI is available.  The following algorithm describes
a procedure by which clients can process ESNIKeys responses as they
arrive to produce addresses for ESNI-capable hosts.
Paragraph (version B):
Clients SHOULD initiate ESNI queries in parallel alongside normal A
or AAAA queries to obtain address information in a timely manner in
the event that ESNI is available.  The following algorithm describes
a procedure by which clients can process ESNI responses as they
arrive to produce addresses for ESNI-capable hosts.
Paragraph (version A):
In order to send an encrypted SNI, the client MUST first select one
of the server ESNIKeyShareEntry values and generate an (EC)DHE share
in the matching group.  This share will then be sent to the server in
the "encrypted_sni" extension and used to derive the SNI encryption
key.  It does not affect the (EC)DHE shared secret used in the TLS
key schedule.  It MUST also select an appropriate cipher suite from
the list of suites offered by the server.  If the client is unable to
select an appropriate group or suite it SHOULD ignore that ESNIKeys
value and MAY attempt to use another value provided by the server.
(Recall that servers might provide multiple ESNIKeys in response to a
ESNI record query.)  The client MUST NOT send encrypted SNI using
groups or cipher suites not advertised by the server.
Paragraph (version B):
In order to send an encrypted SNI, the client MUST first select one
of the server ESNIKeyShareEntry values and generate an (EC)DHE share
in the matching group.  This share will then be sent to the server in
the "encrypted_sni" extension and used to derive the SNI encryption
key.  It does not affect the (EC)DHE shared secret used in the TLS
key schedule.  It MUST also select an appropriate cipher suite from
the list of suites offered by the server.  If the client is unable to
select an appropriate group or suite it SHOULD ignore that ESNIKeys
value and MAY attempt to use another value provided by the server.
(Recall that servers might provide multiple ESNIRecord values in
response to a ESNI record query, each containing an ESNIKeys value.)
The client MUST NOT send encrypted SNI using groups or cipher suites
not advertised by the server.
Paragraph (version A):
In comparison to I-D.kazuho-protected-sni, wherein DNS Resource
Records are signed via a server private key, ESNIKeys have no
authenticity or provenance information.  This means that any attacker
which can inject DNS responses or poison DNS caches, which is a
common scenario in client access networks, can supply clients with
fake ESNIKeys (so that the client encrypts SNI to them) or strip the
ESNIKeys from the response.  However, in the face of an attacker that
controls DNS, no SNI encryption scheme can work because the attacker
can replace the IP address, thus blocking client connections, or
substituting a unique IP address which is 1:1 with the DNS name that
was looked up (modulo DNS wildcards).  Thus, allowing the ESNIKeys in
the clear does not make the situation significantly worse.
Paragraph (version B):
In comparison to I-D.kazuho-protected-sni, wherein DNS Resource
Records are signed via a server private key, ESNI records have no
authenticity or provenance information.  This means that any attacker
which can inject DNS responses or poison DNS caches, which is a
common scenario in client access networks, can supply clients with
fake ESNI records (so that the client encrypts SNI to them) or strip
the ESNI record from the response.  However, in the face of an
attacker that controls DNS, no SNI encryption scheme can work because
the attacker can replace the IP address, thus blocking client
connections, or substituting a unique IP address which is 1:1 with
the DNS name that was looked up (modulo DNS wildcards).  Thus,
allowing the ESNI records in the clear does not make the situation
significantly worse.
Paragraph (version A):
This design depends upon DNS as a vehicle for semi-static public key
distribution.  Server operators may partition their private keys
however they see fit provided each server behind an IP address has
the corresponding private key to decrypt a key.  Thus, when one ESNI
key is provided, sharing is optimally bound by the number of hosts
that share an IP address.  Server operators may further limit sharing
by sending different Resource Records containing ESNIKeys with
different keys using a short TTL.
Paragraph (version B):
This design depends upon DNS as a vehicle for semi-static public key
distribution.  Server operators may partition their private keys
however they see fit provided each server behind an IP address has
the corresponding private key to decrypt a key.  Thus, when one ESNI
key is provided, sharing is optimally bound by the number of hosts
that share an IP address.  Server operators may further limit sharing
by sending different Resource Records containing ESNIRecord and
ESNIKeys values with different keys using a short TTL.
Paragraph (version A):
Assuming ESNIKeys retrieved from DNS are validated, e.g., via DNSSEC
or fetched from a trusted Recursive Resolver, spoofing a server
operating in Split Mode is not possible.  See cleartext-dns for more
details regarding cleartext DNS.
Paragraph (version B):
Assuming ESNI records retrieved from DNS are validated, e.g., via
DNSSEC or fetched from a trusted Recursive Resolver, spoofing a
server operating in Split Mode is not possible.  See cleartext-dns
for more details regarding cleartext DNS.