Hello Willy. Thanks a lot for the discussion on the Jetty issue report. I hope this can be fixed somehow.
In the meantime, I have implemented a workaround, duplicating the backend, one with proto h2 support (h2_backend) and another without (h1_backend). And then I have this in the frontend: use_backend h1_backend if HTTP_1.0 or HTTP_1.1 default_backend h2_backend Also thanks a lot for the connection share warning related to the proxy protocol. We have switched to option forwardfor instead, which I understand is the right option at the http level. We will replace it by option forwarded once Ubuntu updates haproxy package version. Regards, Óscar On Fri, Feb 24, 2023 at 4:13 PM Óscar Frías Barranco <ofr...@gmail.com> wrote: > Hello Willy. > > Thank you very much for the detailed answer. I have reported this in > Jetty issue tracker, I hope they can support this use case: > https://github.com/eclipse/jetty.project/issues/9436 > > Kind regards, > Óscar > > > On Fri, Feb 24, 2023 at 2:44 PM Willy Tarreau <w...@1wt.eu> wrote: > >> Hello, >> >> On Fri, Feb 24, 2023 at 02:19:30PM +0100, Óscar Frías Barranco wrote: >> > Hello >> > >> > I am using haproxy 2.4.18 with a frontend configured with alpn >> h2,http/1.1 >> > >> > The problem that I am facing is that if I add "proto h2" to the >> backends, >> > when a remote client connects to the frontend using HTTP 1.1, the >> request >> > is sent to the backend server without copying the "Host" header to the >> > ":authority" pseudo-header. >> >> This is normal and expected, it complies with the spec that is pretty >> strict about this: >> >> https://www.rfc-editor.org/rfc/rfc7540#section-8.1.2.3 >> >> The ":authority" pseudo-header field includes the authority >> portion of the target URI ([RFC3986], Section 3.2). The authority >> MUST NOT include the deprecated "userinfo" subcomponent for "http" >> or "https" schemed URIs. >> >> To ensure that the HTTP/1.1 request line can be reproduced >> accurately, this pseudo-header field MUST be omitted when >> translating from an HTTP/1.1 request that has a request target in >> origin or asterisk form (see [RFC7230], Section 5.3). >> >> and was further refined in the updated spec: >> >> >> https://www.rfc-editor.org/rfc/rfc9113#name-request-pseudo-header-field >> >> The ":authority" pseudo-header field conveys the authority portion >> (Section >> 3.2 of [RFC3986]) of the target URI (Section 7.1 of [HTTP]). >> (...) >> An intermediary that forwards a request over HTTP/2 MUST construct an >> ":authority" pseudo-header field using the authority information from >> the >> control data of the original request, unless the original request's >> target URI >> does not contain authority information (in which case it MUST NOT >> generate >> ":authority"). Note that the Host header field is not the sole source >> of this >> information; see Section 7.2 of [HTTP]. >> >> If the HTTP/1 request contains an authority part, it will appear there. >> Otherwise only the host is used. In summary, the H2 request looks very >> close to the H1 one: Host conveys Host, authority conveys authority. >> >> > This causes the application server (Jetty in my case) to report the >> backend >> > server numeric IP address as the server name instead of reporting the >> web >> > domain (which is in the Host header) as one would expect. The URI >> reported >> > at the application level is also wrong (numeric instead of the domain) >> for >> > the same reason I suppose. >> >> Given that :authority is not mandatory, I presume there should be at >> least an option in Jetty to report the Host when it is missing. For >> example RFC7540 used to hint about this: >> >> Clients >> that generate HTTP/2 requests directly SHOULD use the ":authority" >> pseudo-header field instead of the Host header field. An >> intermediary that converts an HTTP/2 request to HTTP/1.1 MUST >> create a Host header field if one is not present in a request by >> copying the value of the ":authority" pseudo-header field. >> >> > If the remote user connects to the frontend with HTTP/2 everything is >> > correct (I assume that is because the :authority pseudo header was >> already >> > in there). >> > >> > If I remove "proto h2" from the backend, everything is OK too (because >> in >> > this case :authority is converted to a Host header when connecting to >> the >> > backend). >> > >> > Is there something I can do to fix this? Is this a bug (either from >> > haproxy or Jetty) ? >> >> I suspect it's not a bug but a config decision on Jetty's side. >> >> Particularly, a few years ago some vulnerabilities were exposed in H2 >> agents not strictly following the spec regarding host vs :authority, >> making combinations of such agents rather "fun". It's very possible >> that some implementations have decided to restrict the fallbacks by >> default and to only rely on :authority unless configured to look at >> Host when missing, according to the spec. >> >> If required there is a hack that can be used to force an authority. >> If you force an authority in your request it should normally work: >> >> http-request set-uri https://%[req.hdr(host)]%[pathq] >> >> But it would be cleaner to make sure the server accepts a request that >> only has a host and no authority. >> >> Regards, >> Willy >> >