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 >