- From: Willy Tarreau <w@1wt.eu>
- Date: Wed, 18 Dec 2024 14:35:20 +0100
- To: Glenn Strauss <gs-lists-ietf-http-wg@gluelogic.com>
- Cc: HTTP Working Group <ietf-http-wg@w3.org>, mcmanus@ducksong.com
Hi Glenn, On Wed, Dec 18, 2024 at 06:57:14AM -0500, Glenn Strauss wrote: > HTTP/1.1 Upgrade overloads the request. > > There is an HTTP 1.1 request and there is an HTTP/1.1 Upgrade request. > > If the Upgrade is not handled, the HTTP request proceeds. > > If the Upgrade is to be handled, then the request be must read in full > prior to the Upgrade taking effect on data *after the full request* > received from the client. There is a danger here for exposure to > request smuggling if various intermediaries handle or do not handle the > request body differently. I pretty much agree with all of this, and that's clearly the problem here of switching to CONNECT which doesn't offer option for marking a boundary on a request payload. > Some of these issues were discussed earlier this year regarding > Security Considerations for Optimistic Use of HTTP Upgrade > https://datatracker.ietf.org/doc/draft-schwartz-httpbis-optimistic-upgrade/ > both on list and at the IETF meetings, e.g. > https://httpwg.org/wg-materials/ietf120/minutes.html#security-considerations-for-optimistic-use-of-http-upgrade----ben-schwartz > > (I think on the list) I made a suggestion that the draft limit future > Upgrade tokens for use in requests *without* a request body and with > idempotent HTTP request methods. > > I still feel that way and so for these reasons would oppose adding > complexity to extend RFC8441 CONNECT to allow a request body. I'm not strongly against that, it's just that we may be ossifying some applications what will require H1 exclusively and forever. But hey, we have set-cookie as well... > Why does the docker engine API use POST along with Upgrade? I have no idea. But I can understand how some implementors could consider that they need to open a bidirectional channel not working on HTTP boundaries, hence an upgrade, and that the initial context to start with is passed as a message body. We could for example imagine that some applications repost the last dumped state of the previous session, which the gateway searches among all known servers, to route the final tunnel request to the proper region/server. That's certainly not the case here but there can be valid use cases (which technically do work). > HTTP POST method is not intrinsically idempotent. > Would it not be better if the docker API sent the POST request, and > separately, depending on success/failure of the POST request, sent > an HTTP/1.1 Upgrade: websocket request via GET? Or even the reverse, request first, then use their protocol to send the data. But anyway I don't know their protocol and am not qualified to judge their choice. Maybe in their context it's the best one. > From my quick look in Moby, the open source repo for community Docker: > > Search for "Upgrade:" to see the examples > Upgrade: tcp and Upgrade: h2c > https://github.com/moby/moby/blob/master/api/swagger.yaml > > Since swagger.yaml mentions Upgrade: h2c, I'll note that lighttpd will > ignore HTTP/1.1 Upgrade: h2c if there is a non-zero HTTP request body > included with HTTP/1.1 Upgrade: h2c. That is done to avoid the > potential for request smuggling with HTTP/1.1 Upgrade: h2c. Same here. Actually it's not just about smuggling, it's also about bypassing everything (routing rules, filtering etc). > At the moment, I do not know why Docker API is using POST instead of GET > and if the POST even has a body, or if it happens to use > Transfer-Encoding: chunked even in cases where it could explicitly use > Content-Length: 0. I don't know either, I don't even have these tools nor do I know how to test them. And if we had to try each and every strangely behaving application, it would require more people than are likely subscribed to this list! > > [...] but the problem remains that the mechanism proposed by > > RFC8441 doesn't offer provisions for completely transporting H1 > > over H2, nor replacing H1 with H2. [...] > > True. Perhaps HTTP/1.1 RFCs should be updated to deprecate > non-zero request body and use an idempotent method when including > an Upgrade token with the request? Similar to your last suggestion: > > > - or we could do nothing and consider that some parts of HTTP/1 will > > remain HTTP/1 forever and will not be transportable over newer > > versions. I'm not fundamentally against it but it would warrant > > some extra documentation (especially in the H1 related specs) to > > discourage such use so that we make sure no new protocol adopts > > them and stay stuck in a corner. > > BTW, there is already another outstanding issue mentioned on this list > (but not followed with an errata) about HTTP/2 extended CONNECT breaking > HTTP Digest authentication for an HTTP/1.x request translated to HTTP/2 > since the HTTP method is included in the digest, but the HTTP/1.1 > request sent over HTTP/2 uses HTTP method CONNECT. [1] Ben noted that > the issue may also apply to MASQUE protocols. > > [1] https://lists.w3.org/Archives/Public/ietf-http-wg/2024JulSep/0169.html Hmmm interesting. Actually this class of problems can probably be extended to any info passed in a the request as the method or a header field that's normally not expected with CONNECT. After all, section 5 of 8441 says: The :protocol pseudo-header field MUST be included in the CONNECT request, and it MUST have a value of "websocket" to initiate a WebSocket connection on an HTTP/2 stream. Other HTTP request and response-header fields, such as those for manipulating cookies, may be included in the HEADERS with the CONNECT method as usual. This request replaces the GET-based request in [RFC6455] and is used to process the WebSockets opening handshake. So there's a way to read it as "any field including content-length...". And for the original method a specific header could be imagined. All of this just doesn't have totally obvious implications and may require implementors to be very careful about (which is already the case in fact). Cheers, Willy
Received on Wednesday, 18 December 2024 13:35:30 UTC