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
>

Reply via email to