Subject: [Masque] scheme and authority for CONNECT-UDP (and other new CONNECT-* methods)

From: Erik Nygren <[email-masked]>
Date: Tue, 9 Mar 2021 19:43:53 -0500

Following up on today's question on what should be used for scheme
and authority for CONNECT-UDP, I am thinking we may want to reconsider
the overall approach for scheme, authority, and path for CONNECT-UDP
and any other new CONNECT-* methods.  We may even wish to consider
defining a new CONNECT-TCP method for QUIC.

As a service operator, the CONNECT method has problematic semantics
that don't work well for providing a multi-tenant service.  It is defined
(in H2 at least)
to have no scheme and no path, and its authority is the same name
as the hostname of the connect target.  This makes it problematic:
there's effectively no Host header in the sense that all other HTTP requests
have a Host header (or H2 :authority) that will match the TLS ServerName.
Given that many HTTP servers apply policy on an Origin basis
(scheme+authority+port)
this policy isn't applicable to CONNECT in a meaningful way.  ie, what you
generally
want to apply configuration / authentication / policy on is the server Host
name,
not on the target name.

We clearly can't change the CONNECT semantics here, but we should avoid
introducing another new weird case that varies from HTTP semantics
and which makes providing a multi-tenant service hard.

What I'd propose for CONNECT-UDP is:

* We keep :scheme as "https"
* We keep :authority as the Host header / TLS ServerName for the connection
to the proxy
* We encode the target in :path

So as an example:

:method = CONNECT-UDP
:authority = masque-proxy.example.net
:path = /www.example.com?port=3568
:scheme = https

(There are a few different ways to encode :path)

We may wish to consider defining a parallel CONNECT-TCP in MASQUE
that provides similar semantics to CONNECT but which uses this structure,
that will be much more conducive to running services.

Best, Erik

---

From: Ben Schwartz <[email-masked]>
Date: Wed, 10 Mar 2021 16:34:26 -0500

I think you've hit upon something important here.  Let me go one step
further: what if we simply define one new method (codename "DG_FLOW").  Its
body is a delimited stream of concatenated reliable datagrams.  In HTTP/3,
it can have associated unreliable datagrams.  Its target is a standard
URI.  It's fully streaming both ways and never cacheable.  That's the whole
definition of the method.

MASQUE would use this with URIs with the authority being the proxy, like
your examples.  Between the URI and the headers, the request would encode
in a standardized way that it is requesting a UDP, TCP, or IP forwarding
service to some destination.

This improves "separation of concerns" for gateways.  For example, we
wouldn't have to worry about convincing CDN operators to add support for
"CONNECT-IP" if it's defined in the future.  Once they've added DG_FLOW,
their customers can send flows of whatever.

It also lowers the barrier to experimentation with new weird proxying
modes.  You want to send ethernet frames over HTTP for some kind of L2
VPN?  Some kind of RTP-ish thing for WebRTC?  Go for it; no need to keep
adding HTTP methods.

On Tue, Mar 9, 2021 at 7:44 PM Erik Nygren <[email-masked]> wrote:

> want to apply configuration / authentication / policy on is the server
> Host name,
> not on the target name.
>
> * We keep :authority as the Host header / TLS ServerName for the
> connection to the proxy
> --
> Masque mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/masque
>

---

From: Erik Nygren <[email-masked]>
Date: Wed, 10 Mar 2021 17:30:56 -0500

Interesting thought to just have a common new method like DG-FLOW.

Is there any reason why WEBTRANS wouldn't want to do the same thing?
ie, why do webtrans and masque need different things here?
The biggest difference may just be in how the endpoints are provisioned?

Martin Thompson also points out that it makes sense to use
a URI template for the path rather than hard-coding one in the
specification.

I don't have a strong opinion on whether this is a new CONNECT-DG method
with details coming in some other form (path and headers) or whether
we have separate methods.  If we have CONNECT-DG would then we want
a CONNECT-STREAM analogue?

   Erik

On Wed, Mar 10, 2021 at 4:34 PM Ben Schwartz <[email-masked]> wrote:

>> this policy isn't applicable to CONNECT in a meaningful way.  ie, what
>> you generally

---

From: Victor Vasiliev <[email-masked]>
Date: Wed, 10 Mar 2021 17:41:27 -0500

For what it's worth, WebTransport uses CONNECT as defined in RFC 8441,
which redefines ":authority", ":scheme" and ":path" with CONNECT to mean
what they usually mean for HTTP resources.

On Wed, Mar 10, 2021 at 5:31 PM Erik Nygren <[email-masked]> wrote:

>>> that don't work well for providing a multi-tenant service.  It is
>>> defined (in H2 at least)

---

From: Mike Bishop <[email-masked]>
Date: Mon, 29 Mar 2021 21:03:16 +0000

That works for WebTransport, since you’re really not connecting to another host, so you don’t actually need to communicate two hostnames.  But for proxying, the core requirement is that a multi-tenancy-friendly CONNECT-* method needs to communicate both the proxy and the target hostname.  That’s problematic with legacy CONNECT and might be an argument for replacing it.

From: Masque <[email-masked]> On Behalf Of Victor Vasiliev
Sent: Wednesday, March 10, 2021 5:41 PM
To: Erik Nygren <[email-masked]>
Cc: Ben Schwartz <[email-masked]>; MASQUE <[email-masked]>
Subject: Re: [Masque] scheme and authority for CONNECT-UDP (and other new CONNECT-* methods)

For what it's worth, WebTransport uses CONNECT as defined in RFC 8441, which redefines ":authority", ":scheme" and ":path" with CONNECT to mean what they usually mean for HTTP resources.

On Wed, Mar 10, 2021 at 5:31 PM Erik Nygren <[email-masked]<mailto:[email-masked]>> wrote:
Interesting thought to just have a common new method like DG-FLOW.

Martin Thompson also points out that it makes sense to use
a URI template for the path rather than hard-coding one in the specification.

   Erik

On Wed, Mar 10, 2021 at 4:34 PM Ben Schwartz <[email-masked]<mailto:[email-masked]>> wrote:
I think you've hit upon something important here.  Let me go one step further: what if we simply define one new method (codename "DG_FLOW").  Its body is a delimited stream of concatenated reliable datagrams.  In HTTP/3, it can have associated unreliable datagrams.  Its target is a standard URI.  It's fully streaming both ways and never cacheable.  That's the whole definition of the method.

MASQUE would use this with URIs with the authority being the proxy, like your examples.  Between the URI and the headers, the request would encode in a standardized way that it is requesting a UDP, TCP, or IP forwarding service to some destination.

This improves "separation of concerns" for gateways.  For example, we wouldn't have to worry about convincing CDN operators to add support for "CONNECT-IP" if it's defined in the future.  Once they've added DG_FLOW, their customers can send flows of whatever.

It also lowers the barrier to experimentation with new weird proxying modes.  You want to send ethernet frames over HTTP for some kind of L2 VPN?  Some kind of RTP-ish thing for WebRTC?  Go for it; no need to keep adding HTTP methods.

On Tue, Mar 9, 2021 at 7:44 PM Erik Nygren <[email-masked]<mailto:[email-masked]>> wrote:

As a service operator, the CONNECT method has problematic semantics
that don't work well for providing a multi-tenant service.  It is defined (in H2 at least)
to have no scheme and no path, and its authority is the same name
as the hostname of the connect target.  This makes it problematic:
there's effectively no Host header in the sense that all other HTTP requests
have a Host header (or H2 :authority) that will match the TLS ServerName.
Given that many HTTP servers apply policy on an Origin basis (scheme+authority+port)
this policy isn't applicable to CONNECT in a meaningful way.  ie, what you generally
want to apply configuration / authentication / policy on is the server Host name,
not on the target name.

* We keep :scheme as "https"
* We keep :authority as the Host header / TLS ServerName for the connection to the proxy
* We encode the target in :path

So as an example:

:method = CONNECT-UDP
:authority = masque-proxy.example.net<http://masque-proxy.example.net>
:path = /www.example.com?port=3568<http://www.example.com?port=3568>
:scheme = https

Best, Erik

--
Masque mailing list
[email-masked]<mailto:[email-masked]>
https://www.ietf.org/mailman/listinfo/masque
--
Masque mailing list
[email-masked]<mailto:[email-masked]>
https://www.ietf.org/mailman/listinfo/masque