Re: Can proxies forward extended CONNECT in HTTP-version and protocol-agnostic manner?

On Wed, Oct 4, 2023 at 11:51 PM Kazuho Oku <kazuhooku@gmail.com> wrote:

> Hi Lucas, Ben, David,
>
> Thank you for your responses.
>
> 2023年10月4日(水) 14:50 David Schinazi <dschinazi.ietf@gmail.com>:
>
>> Hi folks,
>>
>> The original analysis seems to focus on the request and response. For
>> those, I agree with your analysis. However, things get more complicated
>> after the protocol tunnel is established. In h1 and h2, the only available
>> HTTP-transport-layer elements are a bidirectional byte stream, so proxying
>> the bytes unmodified should be safe. In h3, it gets more complicated
>> because of things like datagrams. Now if you just blindly copy the request
>> stream's bytestream, you're losing semantic value. (Note that this also
>> applies to h2, as one could in theory write an extension to h2 that defines
>> new capabilities at the h2 framing layer.) As Ben points out, an
>> implementation that supports RFC 9297 could look at datagrams and the
>> Capsule-Protocol header, but that doesn't help with other extensions.
>> Another example is WebTransport and the way it ties other QUIC streams to
>> the WebTransport session.
>>
>> So, if the goal is to build an intermediary that translates automatically
>> between HTTP versions without understanding the protocol, it will fail any
>> time a new extension to HTTP itself is required for a protocol to operate.
>> But that's not a deal breaker, just something to consider. Those extensions
>> to HTTP require settings, so the client shouldn't be using those protocols
>> if the intermediary hasn't sent the corresponding setting. So I guess it
>> comes down to: if an intermediary wants to do this, it really needs to
>> properly handle translating all of the extensions that it supports.
>>
>
> I totally agree with this analysis.
>
>
>> To throw one more wrench into these gears, the Capsule-Protocol header
>> was unfortunately defined to be optional so an intermediary that receives
>> HTTP/3 :protocol=connect-udp but without Capsule-Protocol=?1 won't know
>> what to do with datagrams it receives. I vaguely remember that the intent
>> of the proponents of making Capsule-Protocol optional was explicitly to
>> prevent doing this type of conversion.
>>
>
> Oh I missed the fact that the capsule-protocol header is optional.
>
> Even if that is the case, theoretically an intermediary can discover that
> the streams must have been using capsule protocol at the moment it receives
> a HTTP datagram, then retroactively decode the bytes exchanged on the
> streams to determine whether the boundaries of each capsule is, and start
> transcoding HTTP datagrams to capsules or vice versa. Such design is
> possible because IIRC RFC 9297 requires use of capsule protocol on the
> streams at the same time.
>

That's not right. RFC 9297 does not require using the Capsule protocol:
<<Additionally, HTTP extensions can use HTTP Datagrams with their own data
stream protocol.>>
https://www.rfc-editor.org/rfc/rfc9297#section-3.5-10
It's allowed to create a new :protocol that uses HTTP Datagrams with a
custom stream encoding.

But yeah I agree that it's tricky and that it is questionable if such an
> approach would make sense in the long run.
>
> I think I am becoming convinced that probably having an allow list is the
> correct answer here.
>

That would be safe. Implement the automatic conversion but only enable it
for an allowlist of :protocols. New ones are rare so keeping that list
up-to-date shouldn't be too hard.

For the virtue of laziness as a programmer, maybe I can let the users
> configure the allow list and make it their problem instead of mine :-)
>
>
>> Anyway, apologies for the long ramble. Based on all this, it's probably
>> not safe to convert unknown HTTP upgrade tokens between HTTP versions.
>>
>> David
>>
>> On Wed, Oct 4, 2023 at 1:56 PM Ben Schwartz <bemasc@meta.com> wrote:
>>
>>> I think conversions between HTTP/2 and HTTP/1.1 would require a new
>>> standards-track RFC to codify the usage of "GET" (and possibly revise our
>>> interpretation of the "HTTP" and "TLS" upgrade tokens), but otherwise it
>>> should be fine.  That document would have to incorporate some
>>> requirements related to
>>> https://datatracker.ietf.org/doc/draft-schwartz-httpbis-optimistic-upgrade/,
>>> which hasn't gotten enough comments yet.  Please review!
>>>
>>> Conversions involving HTTP/3 are more interesting due to datagrams.  If
>>> the Capsule-Protocol header is present, then conversions between H2 and H3
>>> are well-defined.  Otherwise, I don't think it's safe: the H3 hop could
>>> send a datagram, and the H2 hop wouldn't know what to do with it.  Silently
>>> blackholing all datagrams, on a request that claims to be successful, is
>>> not a good solution.
>>>
>>> --Ben Schwartz
>>>
>>> ------------------------------
>>> *From:* Lucas Pardue <lucaspardue.24.7@gmail.com>
>>> *Sent:* Wednesday, October 4, 2023 4:01 PM
>>> *To:* Kazuho Oku <kazuhooku@gmail.com>
>>> *Cc:* HTTP Working Group <ietf-http-wg@w3.org>
>>> *Subject:* Re: Can proxies forward extended CONNECT in HTTP-version and
>>> protocol-agnostic manner?
>>>
>>> Hi Kazuho, On Wed, Oct 4, 2023 at 8: 56 PM Kazuho Oku <kazuhooku@
>>> gmail. com> wrote: Hi folks, As a proxy developer, I would like to
>>> implement a tunnel for extended CONNECT requests in a HTTP-version agnostic
>>> way, without knowing how each
>>> ZjQcmQRYFpfptBannerStart
>>> This Message Is From an External Sender
>>>
>>> ZjQcmQRYFpfptBannerEnd
>>> Hi Kazuho,
>>>
>>>
>>>
>>> On Wed, Oct 4, 2023 at 8:56 PM Kazuho Oku <kazuhooku@gmail.com> wrote:
>>>
>>> Hi folks,
>>>
>>> As a proxy developer, I would like to implement a tunnel for extended
>>> CONNECT requests in a HTTP-version agnostic way, without knowing how each
>>> protocol as indicated by the :protocol: pseudo header is to be transcoded.
>>>
>>> The request can come in any HTTP version, then forwarded in any HTTP
>>> version.
>>>
>>> If we look at the existing RFCs and drafts, it seems to me that that's
>>> possible.
>>>
>>> Websocket, connect-udp, connect-ip, connect-ethernet, connect-tcp, they
>>> all use GET + upgrade in HTTP/1.1, use extended CONNECT in H2 and H3.
>>> Therefore, we can have one shared logic to convert between the HTTP
>>> versions that is ignorant of the upgrade token being specified.
>>>
>>> But because each upgrade protocol defines its own mapping to H1, H2 and
>>> H3, the question is: can we assume that we'd be reusing this design pattern
>>> so that we can have proxying logic that is agnostic to the upgrade token?
>>>
>>> Specifically, I think we can break down the question to:
>>>
>>> 1. Can we transcode H2 extended CONNECT requests to H3, or vice versa? I
>>> think the answer is yes.
>>>
>>> 2. Can we transcode H2 / H3 extended CONNECT requests to H1 GET +
>>> upgrade? Maybe the answer is yes.
>>>
>>> 3. Can we transcode H1 GET + upgrade into H2 / H3 extended CONNECT? I'm
>>> not sure if this is possible with h2c. Is it just enough to have a deny
>>> list that contains h2c?
>>>
>>>
>>> I tend to agree with your answers. FWIW we obsoleted `h2c` in RFC9113
>>> [1] so I think making an exception for it (deny list) is fine.
>>>
>>> Cheers,
>>> Lucas
>>>
>>>
>>> [1] = https://www.rfc-editor.org/rfc/rfc9113.html#section-3.1
>>>
>>>
>>> --
>>> Kazuho Oku
>>>
>>>
>
> --
> Kazuho Oku
>

Received on Thursday, 5 October 2023 17:19:43 UTC