Subject: [DNSOP] SVCB and HTTPSSVC records: draft-nygren-dnsop-svcb-httpssvc-00

From: Erik Nygren <[email-masked]>
Date: Tue, 24 Sep 2019 09:17:59 -0400

Following discussions around the "HTTPSSVC" record proposal in Montreal
with the DNSOP, HTTP and TLS WGs, we've updated what was previously
"draft-nygren-httpbis-httpssvc-03".  The new version is
"draft-nygren-dnsop-svcb-httpssvc-00".   This incorporates much of the
feedback from the WG discussions, as well as feedback from discussions with
the TLS WG (as we'd like to see this replace the need for a separate ESNI
record).

In particular, it generalizes the record into a new "SVCB" record which
doesn't have any protocol-specific semantics.  It also defines an
"HTTPSSVC" record that is compatible with SVCB (sharing a wire-format and
parameter registry) and which defines the HTTP(S)-specific semantics such
as bindings to Alt-Svc.  Other protocols can either define bindings
directly to SVCB or can define their own RR Type (which should only ever be
needed if there is a need to use the record at a zone apex).

We'd like to see this adopted by the DNSOP WG.  Until then, issues and PRs
can go against:  https://github.com/MikeBishop/dns-alt-svc

Major changes from "draft-nygren-httpbis-httpssvc-03" include:

* Separation into the SVCB and HTTPSSVC RR Types  (and separated all of the
HTTPS-specific functionality and text to its own portion of the document).
* Elimination of the SvcRecordType field (and making the SvcRecordType
implicit)
* Changing the wire format of parameters from being in Alt-Svc text format
to a more general binary key/value pair format (with a mapping to Alt-Svc
for HTTPSSVC).
* Adding optional "ipv4hint" and "ipv6hint" parameters.
* Quite a few cleanups and clarifications based on input (and we
undoubtedly have more left to go)

This retains support for all of the use-cases that the previous HTTPSSVC
record had (such as for covering the ANAME / CNAME-at-the-zone-apex
use-case).

Feedback is most welcome.  If the TLS WG is going to use this instead of a
separate ESNI record, there is a desire to make progress on this fairy
quickly.

       Erik

---------- Forwarded message ---------
From: <[email-masked]>
Date: Mon, Sep 23, 2019 at 7:01 PM
Subject: New Version Notification for
draft-nygren-dnsop-svcb-httpssvc-00.txt
To: Mike Bishop <[email-masked]>, Erik Nygren <[email-masked]>,
Benjamin Schwartz <[email-masked]>

A new version of I-D, draft-nygren-dnsop-svcb-httpssvc-00.txt
has been successfully submitted by Benjamin Schwartz and posted to the
IETF repository.

Name:           draft-nygren-dnsop-svcb-httpssvc
Revision:       00
Title:          Service binding and parameter specification via the DNS
(DNS SVCB and HTTPSSVC)
Document date:  2019-09-22
Group:          Individual Submission
Pages:          33
URL:
https://www.ietf.org/internet-drafts/draft-nygren-dnsop-svcb-httpssvc-00.txt
Status:
https://datatracker.ietf.org/doc/draft-nygren-dnsop-svcb-httpssvc/
Htmlized:
https://tools.ietf.org/html/draft-nygren-dnsop-svcb-httpssvc-00
Htmlized:
https://datatracker.ietf.org/doc/html/draft-nygren-dnsop-svcb-httpssvc

Abstract:
   This document specifies the "SVCB" and "HTTPSSVC" DNS resource record
   types to facilitate the lookup of information needed to make
   connections for origin resources, such as for HTTPS URLs.  SVCB
   records allow an origin to be served from multiple network locations,
   each with associated parameters (such as transport protocol
   configuration and keying material for encrypting TLS SNI).  They also
   enable aliasing of apex domains, which is not possible with CNAME.
   The HTTPSSVC DNS RR is a variation of SVCB for HTTPS and HTTP
   origins.  By providing more information to the client before it
   attempts to establish a connection, these records offer potential
   benefits to both performance and privacy.

   TO BE REMOVED: This proposal is inspired by and based on recent DNS
   usage proposals such as ALTSVC, ANAME, and ESNIKEYS (as well as long
   standing desires to have SRV or a functional equivalent implemented
   for HTTP).  These proposals each provide an important function but
   are potentially incompatible with each other, such as when an origin
   is load-balanced across multiple hosting providers (multi-CDN).
   Furthermore, these each add potential cases for adding additional
   record lookups in-addition to AAAA/A lookups.  This design attempts
   to provide a unified framework that encompasses the key functionality
   of these proposals, as well as providing some extensibility for
   addressing similar future challenges.

   TO BE REMOVED: The specific name for this RR type is an open topic
   for discussion.  "SVCB" and "HTTPSSVC" are meant as placeholders as
   they are easy to replace.  Other names might include "B", "SRV2",
   "SVCHTTPS", "HTTPS", and "ALTSVC".

Please note that it may take a couple of minutes from the time of submission
until the htmlized version and diff are available at tools.ietf.org.

The IETF Secretariat

---

From: Bob Harold <[email-masked]>
Date: Tue, 24 Sep 2019 10:23:45 -0400

On Tue, Sep 24, 2019 at 9:18 AM Erik Nygren <[email-masked]> wrote:

> * Separation into the SVCB and HTTPSSVC RR Types  (and separated all of
> the HTTPS-specific functionality and text to its own portion of the
> document).
>    is load-balanced across multiple hosting providers (multi-CDN)..

Looks good to me, hope it gets used!

Several places have text like:

4. DNS Server Behavior
2.
"If at least one record is in AliasForm, ignore all other SVCB records in
the RRSet."

While the records must be 'ignored', it might be noted that they must still
be included in the DNS response, if DNSSEC is in use, so that the
signatures work, I think?

And my opinion - it should encourage use of DNSSEC.

-- 
Bob Harold

---

From: Ben Schwartz <[email-masked]>
Date: Tue, 24 Sep 2019 11:35:06 -0400

On Tue, Sep 24, 2019 at 10:23 AM Bob Harold <[email-masked]> wrote:

>> We'd like to see this adopted by the DNSOP WG.  Until then, issues and
>> PRs can go against:  https://github.com/MikeBishop/dns-alt-svc
>>
>> * Changing the wire format of parameters from being in Alt-Svc text
>> format to a more general binary key/value pair format (with a mapping to
>> Alt-Svc for HTTPSSVC).
>> Feedback is most welcome.  If the TLS WG is going to use this instead of
>> a separate ESNI record, there is a desire to make progress on this fairy
>> quickly.
>>
>>        Erik
>>
> While the records must be 'ignored', it might be noted that they must
> still be included in the DNS response, if DNSSEC is in use, so that the

True.  I've added this to our tracker:
https://github.com/MikeBishop/dns-alt-svc/issues/55

---

From: Jan Včelák <[email-masked]>
Date: Wed, 25 Sep 2019 18:18:43 +0200

On Tue, Sep 24, 2019 at 3:19 PM Erik Nygren wrote:
> Following discussions around the "HTTPSSVC" record proposal in Montreal with the DNSOP, HTTP and TLS WGs, we've updated what was previously "draft-nygren-httpbis-httpssvc-03".  The new version is "draft-nygren-dnsop-svcb-httpssvc-00".   This incorporates much of the feedback from the WG discussions, as well as feedback from discussions with the TLS WG (as we'd like to see this replace the need for a separate ESNI record).

I support adoption of the draft by this working group.

I generally like the content. I think the HTTPSSVC specifics leak into
the generic SVCB specification a little but that could be polished
later and I haven't noticed any outstanding issues.

One thing I'm concerned about is the SvcParamKey wire format (and
registry). You propose that each parameter would have a code point and
a value encoded in a form specific to the parameter type. On one hand
it will lead to compact encoding but on the other hand an introduction
of new parameter type may become complex for the implementers. Have
you considered encoding the parameters in a free form? Maybe as a
string, similarly how SPF configuration is stored in the TXT record.
It could look like this:

example.com.      7200  IN HTTPSSVC 0 svc.example.net. ""
svc.example.net.  7200  IN HTTPSSVC 2 svc3.example.net. "alpn=h3
port=8003 esnikeys=\"ABC...\""

Jan

---

From: Ben Schwartz <[email-masked]>
Date: Wed, 25 Sep 2019 13:17:04 -0400

> port=8003 esnikeys=\"ABC...\""

The original proposal used a text encoding similar to your description.  We
changed to a key-specific encoding due to complaints about the inefficiency
of base64-encoding ESNI keys.  I think the inefficiency of base64 encoding
is tolerable, but we adopted the feedback in favor of a binary encoding.

If the working group would prefer a textual wire format, that can certainly
be done.

The current draft attempts to minimize complexity for implementers by
offering a fully generic encoding for unknown key types.  For example,
"alpn=h3" can also be expressed as "key1=h3", and "port=8003" can also be
expressed as "key2=\031\067".  This encoding may not be convenient, but
hopefully it will reduce the burden of supporting new parameter types.

All of the value formats mentioned in the draft (raw, uint16, base64, IPv4,
IPv6) are already common in zone files.  If future parameters also stick to
popular formats, new parsing code should be minimal.

---

From: Jan Včelák <[email-masked]>
Date: Thu, 26 Sep 2019 12:30:53 +0200

On Wed, Sep 25, 2019 at 7:17 PM Ben Schwartz wrote:
> The original proposal used a text encoding similar to your description.  We changed to a key-specific encoding due to complaints about the inefficiency of base64-encoding ESNI keys.  I think the inefficiency of base64 encoding is tolerable, but we adopted the feedback in favor of a binary encoding.

This is a fair point. I don't have a strong opinion.

> The current draft attempts to minimize complexity for implementers by offering a fully generic encoding for unknown key types.  For example, "alpn=h3" can also be expressed as "key1=h3", and "port=8003" can also be expressed as "key2=\031\067".  This encoding may not be convenient, but hopefully it will reduce the burden of supporting new parameter types.

I agree we need generic encoding. There is a way to express unknown
record types (https://tools.ietf.org/html/rfc3597#section-5) and the
syntax used there is more compact than what you propose. It uses hex
strings instead of escaped decimal values. However its clumsy to work
with records in that syntax and you proposal is better in that sense.

I think this may become the most complex record type we have in DNS so
far. None of the existing registered record types contain a list of
key-value pairs of arbitrary length. Given that there is also a
registry for key types involved it will be fun to implement the
encoder/decoder. But we will have to deal with it. I'm interested in
what others in this working group think.

Thanks, Ben.

Jan

---

From: Vladimír Čunát <[email-masked]>
Date: Thu, 26 Sep 2019 12:40:52 +0200

> with records in that syntax and you proposal is better in that sense.

I'm curious, Is there much motivation for a bit more compactness of the 
*presentation* format?  I consider its design primarily meant for humans.

> what others in this working group think.

I think we should get "implementation experience" from multiple parties 
at least before publishing the RFC (though that's a point far ahead, I 
suppose).

--Vladimir

---

From: Mark Andrews <[email-masked]>
Date: Fri, 27 Sep 2019 09:31:15 +1000

Implementing the encoder isn’t hard but it needs to be clearer that there are specific encodings. It is easy to miss this. I did initially.

-- 
Mark Andrews

> On 26 Sep 2019, at 20:41, Vladimír Čunát <[email-masked]> wrote:
> 
> 
> I'm curious, Is there much motivation for a bit more compactness of the *presentation* format?  I consider its design primarily meant for humans.
> 
> 
> I think we should get "implementation experience" from multiple parties at least before publishing the RFC (though that's a point far ahead, I suppose).
> 
> --Vladimir
> 
> 
> _______________________________________________
> DNSOP mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/dnsop

---

From: Mark Andrews <[email-masked]>
Date: Fri, 27 Sep 2019 10:42:13 +1000

And from an actual implementation.

enum encoding {
        sbpr_text,
        sbpr_port,
        sbpr_ipv4s,
        sbpr_ipv6s,
        sbpr_base64
};

static const struct {
        const char *    name;
        unsigned int    value;
        enum encoding   encoding;
        bool            initial;
} sbpr[] = {
        { "key0=", 0, sbpr_text, true },
        { "alpn=", 1, sbpr_text, true },
        { "port=", 2, sbpr_port, true },
        { "esnikeys=", 3, sbpr_base64, true },
        { "ipv4hint=", 4, sbpr_ipv4s, true },
        { "ipv6hint=", 6, sbpr_ipv6s, true },
};

                switch (sbpr[i].encoding) {
                case sbpr_text:
                        RETERR(multitxt_fromtext(region, target));
                        break;
                case sbpr_port:
                        ul = strtoul(region->base, &e, 10);
                        if (*e != '\0') {
                                return (DNS_R_SYNTAX);
                        }
                        if (ul > 0xffff) {
                                return (ISC_R_RANGE);
                        }
                        RETERR(uint16_tobuffer(ul, target));
                        break;
                case sbpr_ipv4s:
                        do {
                                snprintf(tbuf, sizeof(tbuf), "%*s",
                                         (int)(region->length), region->base);
                                e = strchr(tbuf, ',');
                                if (e != NULL) {
                                        *e++ = 0;
                                        isc_textregion_consume(region,
                                                               e - tbuf);
                                }
                                if (inet_pton(AF_INET, tbuf, abuf) != 1) {
                                        return (DNS_R_SYNTAX);
                                }
                                mem_tobuffer(target, abuf, 4);
                        } while (e != NULL);
                        break;
                case sbpr_ipv6s:
                        do {
                                snprintf(tbuf, sizeof(tbuf), "%*s",
                                         (int)(region->length), region->base);
                                e = strchr(tbuf, ',');
                                if (e != NULL) {
                                        *e++ = 0;
                                        isc_textregion_consume(region,
                                                               e - tbuf);
                                }
                                if (inet_pton(AF_INET6, tbuf, abuf) != 1) {
                                        return (DNS_R_SYNTAX);
                                }
                                mem_tobuffer(target, abuf, 16);
                        } while (e != NULL);
                        break;
                case sbpr_base64:
                        RETERR(isc_base64_decodestring(region->base,
                                                       target));
                        break;
                default:
                        INSIST(0);
                        ISC_UNREACHABLE();
                }

                switch(encoding) {
                case sbpr_text:
                        RETERR(multitxt_totext(&r, target));
                        break;
                case sbpr_port:
                        num = uint16_fromregion(&r);
                        n = snprintf(buf, sizeof(buf), "%u", num);
                        INSIST(n > 0 && (unsigned)n < sizeof(buf));
                        RETERR(str_totext(buf, target));
                        break;
                case sbpr_ipv4s:
                        while (r.length > 0U) {
                                INSIST(r.length >= 4U);
                                inet_ntop(AF_INET, r.base, buf, sizeof(buf));
                                RETERR(str_totext(buf, target));
                                isc_region_consume(&r, 4);
                                if (r.length != 0U) {
                                        RETERR(str_totext(",", target));
                                }
                        }
                        break;
                case sbpr_ipv6s:
                        while (r.length > 0U) {
                                INSIST(r.length >= 16U);
                                inet_ntop(AF_INET6, r.base, buf, sizeof(buf));
                                RETERR(str_totext(buf, target));
                                isc_region_consume(&r, 16);
                                if (r.length != 0U) {
                                        RETERR(str_totext(",", target));
                                }
                        }
                        break;
                case sbpr_base64:
                        RETERR(isc_base64_totext(&r, 0, "", target));
                        break;
                default:
                        INSIST(0);
                        ISC_UNREACHABLE();
                }

> On 27 Sep 2019, at 9:31 am, Mark Andrews <[email-masked]> wrote:
> 
>>> record types (
>>> https://tools.ietf.org/html/rfc3597#section-5
>>> ) and the

-- 
Mark Andrews, ISC
1 Seymour St., Dundas Valley, NSW 2117, Australia
PHONE: +61 2 9871 4742              INTERNET: [email-masked]

---

From: Tommy Pauly <[email-masked]>
Date: Fri, 27 Sep 2019 07:59:58 -0700

> On Sep 24, 2019, at 6:17 AM, Erik Nygren <[email-masked]> wrote:
> 
> In particular, it generalizes the record into a new "SVCB" record which doesn't have any protocol-specific semantics.  It also defines an "HTTPSSVC" record that is compatible with SVCB (sharing a wire-format and parameter registry) and which defines the HTTP(S)-specific semantics such as bindings to Alt-Svc.  Other protocols can either define bindings directly to SVCB or can define their own RR Type (which should only ever be needed if there is a need to use the record at a zone apex).
> 
> We'd like to see this adopted by the DNSOP WG.  Until then, issues and PRs can go against:  https://github.com/MikeBishop/dns-alt-svc <https://github.com/MikeBishop/dns-alt-svc>
> * Separation into the SVCB and HTTPSSVC RR Types  (and separated all of the HTTPS-specific functionality and text to its own portion of the document).
> * Elimination of the SvcRecordType field (and making the SvcRecordType implicit)
> * Changing the wire format of parameters from being in Alt-Svc text format to a more general binary key/value pair format (with a mapping to Alt-Svc for HTTPSSVC).
> * Quite a few cleanups and clarifications based on input (and we undoubtedly have more left to go)
> 
> This retains support for all of the use-cases that the previous HTTPSSVC record had (such as for covering the ANAME / CNAME-at-the-zone-apex use-case).
> 
> Feedback is most welcome.  If the TLS WG is going to use this instead of a separate ESNI record, there is a desire to make progress on this fairy quickly.

I wanted to express support for getting this work adopted in DNSOP, and ideally doing so relatively soon so that we can unblock work on ESNI. From an OS implementor perspective, I'd really prefer to have an RR type that can be used for ESNI defined from DNSOP, and done so in a way (as this proposal does) that can be expanded to include other information like Alt-Svc, and even properties like support for DoH, etc.

I'd also ask that if this work is adopted, an early IANA allocation be made for the RR type once the basic record content and format is agreed upon.

Thanks to the authors for their work on this solution!

Best,
Tommy

> From: <[email-masked] <mailto:[email-masked]>>
> Subject: New Version Notification for draft-nygren-dnsop-svcb-httpssvc-00.txt
> To: Mike Bishop <[email-masked] <mailto:[email-masked]>>, Erik Nygren <[email-masked] <mailto:[email-masked]>>, Benjamin Schwartz <[email-masked] <mailto:[email-masked]>>
> 
> 
> 
> Title:          Service binding and parameter specification via the DNS (DNS SVCB and HTTPSSVC)
> URL:            https://www.ietf.org/internet-drafts/draft-nygren-dnsop-svcb-httpssvc-00.txt <https://www.ietf.org/internet-drafts/draft-nygren-dnsop-svcb-httpssvc-00.txt>
> Status:         https://datatracker.ietf.org/doc/draft-nygren-dnsop-svcb-httpssvc/ <https://datatracker.ietf.org/doc/draft-nygren-dnsop-svcb-httpssvc/>
> Htmlized:       https://tools.ietf.org/html/draft-nygren-dnsop-svcb-httpssvc-00 <https://tools.ietf.org/html/draft-nygren-dnsop-svcb-httpssvc-00>
> Htmlized:       https://datatracker.ietf.org/doc/html/draft-nygren-dnsop-svcb-httpssvc <https://datatracker.ietf.org/doc/html/draft-nygren-dnsop-svcb-httpssvc>
> 
> 
> Abstract:
> until the htmlized version and diff are available at tools.ietf.org <http://tools.ietf.org/>.
> 
> The IETF Secretariat
>