<?xml version="1.0" encoding="US-ASCII"?>
<!-- this is version 5 of this xml2rfc template -->
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!ENTITY rfc2119 SYSTEM "https://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml">
<!ENTITY rfc8174 SYSTEM "https://xml.resource.org/public/rfc/bibxml/reference.RFC.8174.xml">
<!ENTITY rfc8446 SYSTEM "https://xml.resource.org/public/rfc/bibxml/reference.RFC.8446.xml">
<!ENTITY rfc8615 SYSTEM "https://xml.resource.org/public/rfc/bibxml/reference.RFC.8615.xml">
<!ENTITY I-D.ietf-tls-esni SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-tls-esni">
<!ENTITY I-D.ietf-tls-svcb-ech SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-tls-svcb-ech">

]>
<?rfc toc="yes"?>
<?rfc symrefs="yes"?>
<?rfc compact="yes"?>
<?rfc subcompact="yes"?>
<?rfc strict="no"?>
<?rfc rfcedstyle="yes"?>
<?rfc comments="yes"?>
<?rfc inline="yes"?>
<rfc category="exp" docName="draft-ietf-tls-wkech-04" ipr="trust200902" >
  <front>
    <title abbrev="Well-Known URI for ECH">A well-known URI for publishing ECHConfigList values.</title>

    <author fullname="Stephen Farrell" initials="S." surname="Farrell">
      <organization>Trinity College Dublin</organization>

      <address>
        <postal>
          <street/>

          <city>Dublin</city>

          <region/>

          <code>2</code>

          <country>Ireland</country>
        </postal>

        <phone>+353-1-896-2354</phone>

        <email>stephen.farrell@cs.tcd.ie</email>
      </address>
    </author>

    <author initials="R." surname="Salz" fullname="Rich Salz">
        <organization>Akamai Technologies</organization>
        <address>
            <email>rsalz@akamai.com</email>
        </address>
    </author>

    <author initials="B." surname="Schwartz" fullname="Benjamin Schwartz">
      <organization>Meta Platforms, Inc.</organization>
      <address>
        <email>ietf@bemasc.net</email>
      </address>
    </author>

    <date year="2023"/>

    <area>Security Area</area>

    <workgroup>TLS</workgroup>

    <keyword>TLS</keyword>

    <keyword>ECH</keyword>

    <abstract>
        <t>
            We define a well-known URI at which an HTTP origin can
            inform an authoritative DNS server, or other interested parties,
            about this origin's Service Bindings, i.e. its "HTTPS" DNS records.
            These instructions can include Encrypted ClientHello (ECH)
            configurations, allowing the origin, in collaboration with DNS
            infrastructure elements, to publish and rotate its own ECH keys.
        </t>
    </abstract>
  </front>

  <middle>
    <section title="Introduction">

        <t>Encrypted ClientHello (ECH)
            <xref target="I-D.ietf-tls-esni"/> for TLS1.3 <xref target="RFC8446"/>
            defines a confidentiality mechanism for server names and other ClientHello content in TLS.
            For many applications, that requires publication of ECHConflgList data structures in the DNS.
            An ECHConfigList structure contains a list of ECHConfig values. Each
            ECHConfig value contains the public component of a key pair
            that will typically be periodically (re-)generated by a web server.
            Many web infrastructures will have an API that can be used to
            dynamically update the DNS RR values containing ECHConfigList values.
            Some deployments however, will not, so web deployments could
            benefit from a mechanism to use in such cases.
        </t>

        <t>
            We define such a mechanism here. Note that this is not intended for
            universal deployment, but rather for cases where the web server
            doesn't have write access to the relevant zone file (or
            equivalent). That zone file will eventually include an HTTPS or SVCB
            RR <xref target="I-D.ietf-tls-svcb-ech"/> containing the ECHConfigList.
            This mechanism is extensible to deliver other kinds of information about
            the origin, that can be of use in these circumstances, but is mainly
            intended to provide the functionality necessary for ongoing management 
            of ECH keys.
        </t>

        <t>
            We use the term "zone factory" for the entity that does have write
            access to the zone file. We assume the zone factory (ZF) can also
            make HTTPS requests to the web server with the ECH keys.
            We define a well-known URI <xref target="RFC8615"/> on the web server that
            allows the ZF to poll for changes to ECHConfigList values. For example, if a web server
            generates new ECHConfigList values hourly and publishes those at the well-known URI,
            the ZF can poll that URI.  When the ZF sees new values, it can check if those work, and if
            they do, then update the zone file and re-publish the zone.
        </t>

        <t>
            If ECH is being operated in "split-mode" then the web server (back-end) can
            similarly poll the ECH front-end at the well-known URI and then create it's own
            value to publish for the ZF to read.
        </t>

        <t>[[The source for this draft is in https://github.com/sftcd/wkesni/
            Issues and PRs are welcome there too.]]
        </t>

      </section>

      <section title="Terminology">
        <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
        "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
        "OPTIONAL" in this document are to be interpreted as described in BCP
        14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only
        when, they appear in all capitals, as shown here.</t>

    <t>We define or re-use the following terms:
    <list style="symbols">
        <t>Zone factory (ZF): an entity that has write-accsss to the DNS</t>
        <t>Front-end (FE): the web server that has an ECH private value. This
            processes the outer ClientHello and attempts ECH decryption.
            The name of FE will typically be the public_name value used in an
            ECHconfig.</t>
       <t>Back-end (BE): the web server that will process the inner ClientHello.
       Note that even if FE and BE are on the same web server, they almost
       certainly have different DNS names.</t>
       <t>Shared-mode: this is where FE and BE are the same web server.</t>
       <t>Split-mode: this refers to the case where FE only does ECH decryption 
          but the TLS session is between the client and BE, which will typically
          be on a different host to FE</t>
       <t>regeninterval: the number of seconds after which the value retrieved
           after acessing a well-known URI may be changed.</t>
    </list>
    </t>

      </section>

    <section title="Example use of the well-known URI for ECH">

        <t>An example deployment could be as follows:

           <list style="numbers">
               <t> Shared-mode ECH web server generates new ECHConfigList values every "regeninterval"
               seconds via some regular, automated process (e.g. a cronjob)</t>
                <t> ECHConfigList values are "current" for an hour, and remain usable
                    for 3 hours from the time of generation</t>
                <t> The cronjob updates the ECHConfigList values in a JSON resource at
                    at https://BE/.well-known/origin-svcb, as shown in
                    <xref target="sample-json"/>.</t>
                <t> On the ZF, another regularaly executed job uses
                    an HTTP client to retrieve this JSON resource.
                    It also attempts to connect to BE using these ECH values and confirms
                    that they are working.</t>
                <t> The ZF observes that the JSON resource
                    has a regeninterval of 3600 seconds, and chooses a DNS
                    TTL of 1800.  It updates the zone file for BE and re-publishes
                    the zone containing only the new ECHConfigList values.</t>
                <t> When regeninterval seconds have passed, the ZF attempts to refresh
                    its cached copy of the JSON resource.  If the resource has changed,
                    it repeats this process.</t>
            </list>
        </t>

    </section>

    <section title="The origin-svcb well-known URI">

         <t>
            If BE wants to convey information to the Zone
            Factory, it publishes the JSON content
            defined in <xref target="jsonstr"/> at:
            https://BE/.well-known/origin-svcb
        </t>

        <t>The well-known URI defined here MUST be an https URL and therefore the ZF
            verifies the correct BE is being accessed. If
            no new ECH value resulting "works," then the
            zone factory SHOULD NOT modify the zone. </t>

        <t>Note that a consequence of the URL above is that back-ends that
            wish to use different ECH settings are very likely to have to
            use different "DocRoot" settings.</t>

    </section>


<section anchor="jsonstr" title="The JSON structure for origin service binding info">

  <t>[[The JSON structure is a work in progress.]]</t>

<figure anchor="sample-json" title="Sample JSON for ECH without aliases" >
<artwork><![CDATA[
    {
        "endpoints": [{
            "regeninterval": 3600,
            "priority": 1,
            "target": "cdn.example.",
            "ech": "AD7+DQA65wAgAC..AA=="
        }, {
            "regeninterval": 3600,
            "priority": 1,
            "port": 8413,
            "ech": "AD7+DQA65wAgAC..AA=="
        }]
    }
  ]]></artwork>
</figure>

<figure anchor="sample-json-alias" title="Sample JSON with aliasing" >
    <artwork><![CDATA[
     {
        "endpoints": [{
            "alias": "cdn1.example.net",
            "regeninterval": 108000
        }, {
            "alias": "cdn2.example.com",
            "regeninterval": 108000
        }]
      }
    ]]></artwork>
</figure>

    <t>
        The JSON file at the well-known URI MUST contain an object
        with an "endpoints" key that contains an array of objects
        that each map to a desired HTTPS/SVCB resource record that
        the back-end would like to see published.

        The "endpoints" array its value is an array whose elements
        each represent HTTPS records in ServiceMode or AliasMode as
        described below. Each element MAY contain
        one or more keys from the JSON HTTP Origin Info registry (see
        IANA Considerations).  The initial registry entries are:
        <list style="symbols">
            <t>
                regeninterval: the number of seconds between key generation
                actions at the origin, i.e. a replacement ECHConfigList may be
                generated this often.
            </t>
            <t>
                priority: The value is a positive integer corresponding to the
                SvcPriority.  If omitted, the zone factory SHOULD infer
                numerically increasing SvcPriority from the order of the
                endpoints array.
            </t>
            <t>
                target: The value is a string containing a fully qualified
                domain name, corresponding to the HTTPS record's TargetName.
                The default value is ".".
            </t>
            <t>
                alias: The value MUST be a DNS name
        that could be used as the TargetName of an HTTPS resource record.
        This indicates that the back-end
        is hosted on the same endpoints as this target, and is equivalent to
        an HTTPS AliasMode record.
        The ZF might implement this directive
        by publishing an AliasMode record, publishing a CNAME record, copying
        HTTPS records from the target zone, or fetching
        https://FE/.well-known/origin-svcb" (if it exists).
        In this case, the regeninterval indicates that BE does
        not plan to change the content at the URL for at least that number of
        seconds.
                If an alias entry is present then any ech and port entries
                (if also present) MUST be ignored.
        </t>
            <t>
                ech: The value is a string containing an ECHConfigList encoded
                in Base64 <xref target="RFC4648"/>, corresponding to the value
                of the "ech" SvcParamKey.
            </t>
            <t>
                port: The value is a non-negative integer, corresponding to
                the value of the "port" SvcParamKey.
            </t>
            <t>
                alpn: The value is a string corresponding to
                the value of the "alpn" SvcParamKey.
                Typically this is likely to be set per back-end.
            </t>
            <t>
                ipv4hints: The value is a string corresponding to
                the value of the "ipv4hints" SvcParamKey.
                Typically this is likely to be set per front-end.
            </t>
            <t>
                ipv6hints: The value is a string corresponding to
                the value of the "ipv6hints" SvcParamKey.
                Typically this is likely to be set per front-end.
            </t>
        </list>
        An empty endpoint object corresponds to an HTTPS record with inferred
        SvcPriority, TargetName=".", and no ECH support.  An empty record of
        this kind can be useful as a simple way to make use of the HTTPS RR
        type's HSTS behavior.
    </t>

    <t>
        [[TODO: What does the zone factory do if it encounters an unrecognized
        field?]]
    </t>

    <t>
        This arrangement provides the following important properties:
        <list style="symbols">
            <t>
                Origins can indicate that different ECHConfigs are used on
                different ports.
            </t>
            <t>
                Origins can indicate that multiple CDNs are in use, each with
                its own ECHConfig.
            </t>
            <t>
                Origins that simply alias to a single target can indicate this
                without copying the ECHConfig and other parameters, which
                can interfere with key rotation and other maintenance.
            </t>
            <t>
                "port" and "target" are generally sufficient to uniquely identify
                a ServiceMode record, so zone factories can use the endpoint list
                to add ECH to pre-existing ServiceMode records that may have other
                SvcParams.
            </t>
        </list>
    </t>

</section>

<section title="Zone factory behaviour">

    <t>ZF SHOULD check that the presented endpoints
        work and provide access to BE before publication.
        A bespoke TLS client may be needed for this check,
        that does not require the ECHConfigList value to have
        already been published in the DNS.
        In order to make such checks, the ZF SHOULD
        attempt to access the well-known URI defined here.
    </t>

    <t>A careful ZF implementation could explode the ECHConfigList value
       presented into "singleton" values with one public key in each,
       and then test each of those separately.</t>

    <t>ZF SHOULD publish all the endpoints
        that are presented in the JSON file that pass
        the checks above.</t>

    <t>ZF SHOULD set a DNS TTL short enough so that any
        cached DNS resource records are likely to have expired before the JSON
        object's content is likely to have changed. The ZF
        MUST attempt to refresh the JSON object and regenerate the zone
        before this time.  This aims to ensure that ECHConfig values
        are not used longer than intended by BE.
    </t>

</section>


    <section title="Security Considerations">
        <t>This document defines another way to publish ECHConfigList values. If the wrong
            keys were read from here and published in the DNS, then clients
            using ECH would do the wrong thing, likely resulting in
            denial of service, or a privacy leak, or worse, when TLS clients attempt to use ECH with
            a back-end web site. So: Don't do that:-)</t>

        <t>
            Although this configuration resource MAY be publicly
            accessible, general HTTP clients SHOULD NOT attempt to use this
            resource in lieu of HTTPS records queries through their preferred
            DNS server for the following reasons:
            <list style="symbols">
                <t>
                    The bootstrap connection would not be able to use ECH,
                    so it would reveal all the information that ECH seeks
                    to protect.
                </t>
                <t>
                    The origin could serve the user with a uniquely
                    identifying configuration, potentially resulting in an
                    unexpected tracking vector.
                </t>
            </list>
        </t>

    </section>

    <section title="Acknowledgements">
        <t>Thanks to Niall O'Reilly for a quick review of -00.</t>
        <t>Stephen Farrell's work on this specification was supported in part by
            the Open Technology Fund.</t>
    </section>

    <section title="IANA Considerations">
        <t>[[TBD: IANA registration of a .well-known. Also TBD - how to handle I18N for
            $FRONTEND and $BACKEND within such a URL.]]</t>

        <t>If approved, this specification requests the creation of an IANA
            registry named "JSON HTTP Origin Info" with a Standards Action
            registration policy, containing a field named "Name"
            whose value is a UTF-8 string.
        </t>

    </section>
  </middle>

  <back>
    <references title="Normative References">
      <?rfc include='reference.RFC.2119'?>
      <?rfc include='reference.RFC.8174'?>
      <?rfc include='reference.RFC.8446'?>
      <?rfc include='reference.RFC.8615'?>
      <?rfc include='reference.RFC.4648'?>
      &I-D.ietf-tls-esni;
      &I-D.ietf-tls-svcb-ech;

    </references>

    <!--
    <references title="Informative References">
    </references>
    -->

    <section title="Change Log ">
      <t>[[RFC editor: please remove this before publication.]]</t>

      <t>The -00 WG draft replaces draft-farrell-tls-wkesni-03.</t>

      <t>
        Version 01 changed from a special-purpose design, carrying only
        ECHConfigs and port numbers, to a more general approach based on
        Service Bindings.
      </t>

      <t>
        Version 02 is just a keep-alive
      </t>

      <t>
        Version 03 reflects some local implementation experience with -02
      </t>

      <t>
        Version 04 matches a proof-of-concept bash script implementation and
        results of IETF-117 discussion.
      </t>

    </section>
  </back>
</rfc>
