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