Welcome! Log In Create A New Profile

Advanced

H2: interoperability issue due to lack of CONTINUATION frame support

Posted by Lukas Tribus 
Hi Willy,


haproxy is currently unable to handle CONTINUATION [1] frames (see
commit 61290ec77 - [2]).

If a client emits a CONTINUATION frame, we will break the connection
and send GOAWAY due to INTERNAL_ERROR. This of course leads to
interoperability issues.

Notably, older Chrome/Chromium releases (50.0.2645.4 and older),
lacking Chromium commit a8bff211e ("Increase sent control frame
fragment size to 16 kB") [3], will cap the maximum control frame size
at 1024 bytes, triggering CONTINUATION, when large headers are used
(long URIs, or large cookies).

How to reproduce?
In Chrome/Chromium 50.0.2645.4 or older, access a very long URI on a
h2 enabled haproxy instance. For example on cdn.haproxy.com [4].

Why are old Chrome/Chromium relevant?
Chrome 49 is the latest release that runs under Windows XP. Yes, I
know, but apparently there are large market segments out there where
this has a real business impact. Chrome 49 and Windows XP support
situation a side, this is not a Chrome bug, but a lack of support of a
H2 feature in haproxy. Other corner cases may trigger this issue as
well.

At least 4 different people reported this as an actual
interoperability problem with H2 on discourse [5], [6], additionally
we have 2 reports of results of a RFC7540 test [7], [8], which also
fails due to at least lack of CONTINUATION support.

While this issue is arguably not major - there would have been more
reports otherwise, I do think we should address this issue.

As far as I can see, other major h2 implementations do implement
CONTINUATION support, including nginx and nghttp2.



Best regards,
Lukas



[1] https://tools.ietf.org/html/rfc7540#section-6.10
[2] http://git.haproxy.org/?p=haproxy.git;a=commit;h=61290ec774b311edad0285b90fab979a420d252c
[3] https://github.com/chromium/chromium/commit/a8bff211e9cc3c64f2e6516186131dcdeed59eae
[4] https://cdn.haproxy.com/wp-includes/css/dashicons.min.css?aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[5] https://discourse.haproxy.org/t/http-2-not-compatible-with-filrefox-on-haproxy-1-8-3/2075/32
[6] https://discourse.haproxy.org/t/http-2-chrome-49-on-windows-xp-problems/2931
[7] https://discourse.haproxy.org/t/http2-rfc7540-and-rfc754-test/2042
[8] https://www.mail-archive.com/[email protected]/msg28010.html
Hi Lukas,

On Sat, Sep 01, 2018 at 08:02:45PM +0200, Lukas Tribus wrote:
> Hi Willy,
>
>
> haproxy is currently unable to handle CONTINUATION [1] frames (see
> commit 61290ec77 - [2]).
>
> If a client emits a CONTINUATION frame, we will break the connection
> and send GOAWAY due to INTERNAL_ERROR. This of course leads to
> interoperability issues.

Yes, but arguably these issues should be rare because a client is
expected to fill its frames, so all requests smaller than 16 kB
compressed make no sense to be sent with CONTINUATION.

> Notably, older Chrome/Chromium releases (50.0.2645.4 and older),
> lacking Chromium commit a8bff211e ("Increase sent control frame
> fragment size to 16 kB") [3], will cap the maximum control frame size
> at 1024 bytes, triggering CONTINUATION, when large headers are used
> (long URIs, or large cookies).

Hmmm this is a particularly abusive behaviour considering that the
sole purpose of the CONTINUATION frames was to support extremely
large headers (and these ones were debated a lot) :-(

> How to reproduce?
> In Chrome/Chromium 50.0.2645.4 or older, access a very long URI on a
> h2 enabled haproxy instance. For example on cdn.haproxy.com [4].
>
> Why are old Chrome/Chromium relevant?
> Chrome 49 is the latest release that runs under Windows XP. Yes, I
> know, but apparently there are large market segments out there where
> this has a real business impact.

Sure!

> Chrome 49 and Windows XP support
> situation a side, this is not a Chrome bug, but a lack of support of a
> H2 feature in haproxy. Other corner cases may trigger this issue as
> well.

Definitely.

> At least 4 different people reported this as an actual
> interoperability problem with H2 on discourse [5], [6], additionally
> we have 2 reports of results of a RFC7540 test [7], [8], which also
> fails due to at least lack of CONTINUATION support.
>
> While this issue is arguably not major - there would have been more
> reports otherwise, I do think we should address this issue.

I wanted to address it but the CONTINUATION frame is the worst design
mistake of the H2 protocol and results in layering violations which
make it particularly problematic to implement. In short, while all
frames are independant on each other, this one must absolutely appear
after an existing HEADERS frame and requires to maintain a huge state
of unparsed data to feed to the HPACK decompressor at once after
reassembly. It's even documented in the spec that it can be the source
of a DoS... I'm not saying I don't want to implement them at all, it's
just that in the current state of things, I don't have a clean solution
to propose. We'll have more options once the connection layers are
reversed because we'll have the option to try to parse both HEADERS
and CONTINUATION at once into a temporary buffer and try to decompress
the result. But in any case, CONTINUATION frames support will always
be limited (ie too large HEADERS+CONTINUATION may lead to connection
aborts by placing the decompressor in an unrecoverable state).

> As far as I can see, other major h2 implementations do implement
> CONTINUATION support, including nginx and nghttp2.

And that's sad. It would have been better if most didn't implement this
crap, to get rid of the non-legitimate use cases once for all :-/

I will probably revisit this point after 1.9, at least for protocol
completeness, maybe with an option such as
"waste-memory-and-cpu-to-support-stupid-h2-continuation-frames" or
something as explicit to save people from enabling them by accident :-/

Cheers,
Willy
Hello Willy,


On Sat, 1 Sep 2018 at 21:00, Willy Tarreau <[email protected]> wrote:
> I wanted to address it but the CONTINUATION frame is the worst design
> mistake of the H2 protocol and results in layering violations which
> make it particularly problematic to implement. In short, while all
> frames are independant on each other, this one must absolutely appear
> after an existing HEADERS frame and requires to maintain a huge state
> of unparsed data to feed to the HPACK decompressor at once after
> reassembly. It's even documented in the spec that it can be the source
> of a DoS...

I see, that's about the same nightmare as IPv4 fragmentation, where
supposedly completely stateful routers have to reassemble the IPv4
fragments on MTU mismatched interfaces or to make L4 ACL's actually
match the packets.

Rethinking about this I don't actually think there a lot of other
corner cases triggering CONTINUATION, other than the Chrome 49 case.


> And that's sad. It would have been better if most didn't implement this
> crap, to get rid of the non-legitimate use cases once for all :-/
>
> I will probably revisit this point after 1.9, at least for protocol
> completeness, maybe with an option such as
> "waste-memory-and-cpu-to-support-stupid-h2-continuation-frames" or
> something as explicit to save people from enabling them by accident :-/

Ok. I think with OpenSSL 1.1.1 we may be able to configure ALPN
differently for RSA vs ECC certificates (of the same hostname), so by
not enabling h2 on RSA certificates, we basically disable H2 for
Chrome on Windows XP (Chrome using Microsoft's schannel supporting
only RSA on XP). Chrome on Windows Vista would still be broken (as
schannel on Vista supports ECC certificates), but the market share of
Vista is probably negligible. This should help those that cannot break
this unsupported browser/OS combination and still want to use H2. It's
just a theory though at the moment, I need to test it.



Regards,
Lukas
Hi Lukas,

On Sun, Sep 02, 2018 at 11:55:29AM +0200, Lukas Tribus wrote:
> Ok. I think with OpenSSL 1.1.1 we may be able to configure ALPN
> differently for RSA vs ECC certificates (of the same hostname), so by
> not enabling h2 on RSA certificates, we basically disable H2 for
> Chrome on Windows XP (Chrome using Microsoft's schannel supporting
> only RSA on XP). Chrome on Windows Vista would still be broken (as
> schannel on Vista supports ECC certificates), but the market share of
> Vista is probably negligible. This should help those that cannot break
> this unsupported browser/OS combination and still want to use H2. It's
> just a theory though at the moment, I need to test it.

I like the idea very much! That's indeed something that could be
interesting to study. I even think there's nothing about it that
cannot be done with 1.0.2, it would deserve a test!

Cheers,
Willy
Hello,


On Sun, 2 Sep 2018 at 17:24, Willy Tarreau <[email protected]> wrote:
>
> Hi Lukas,
>
> On Sun, Sep 02, 2018 at 11:55:29AM +0200, Lukas Tribus wrote:
> > Ok. I think with OpenSSL 1.1.1 we may be able to configure ALPN
> > differently for RSA vs ECC certificates (of the same hostname), so by
> > not enabling h2 on RSA certificates, we basically disable H2 for
> > Chrome on Windows XP (Chrome using Microsoft's schannel supporting
> > only RSA on XP). Chrome on Windows Vista would still be broken (as
> > schannel on Vista supports ECC certificates), but the market share of
> > Vista is probably negligible. This should help those that cannot break
> > this unsupported browser/OS combination and still want to use H2. It's
> > just a theory though at the moment, I need to test it.
>
> I like the idea very much! That's indeed something that could be
> interesting to study. I even think there's nothing about it that
> cannot be done with 1.0.2, it would deserve a test!

I tried it and it works fine, crt-list looking like this:
/etc/private/ssl/sitecert-rsa.pem [alpn http/1.1]
/etc/private/ssl/sitecert-ecc.pem [alpn h2,http/1.1]

However, openssl 1.1.1 (or boringssl) is required for this, also see
commit 84e417d85934 ("MINOR: ssl: support Openssl 1.1.1 early callback
for switchctx"). I doubt this can be done with older openssl.


Regards,
Lukas
On Sun, Sep 02, 2018 at 09:24:33PM +0200, Lukas Tribus wrote:
> Hello,
>
>
> On Sun, 2 Sep 2018 at 17:24, Willy Tarreau <[email protected]> wrote:
> >
> > Hi Lukas,
> >
> > On Sun, Sep 02, 2018 at 11:55:29AM +0200, Lukas Tribus wrote:
> > > Ok. I think with OpenSSL 1.1.1 we may be able to configure ALPN
> > > differently for RSA vs ECC certificates (of the same hostname), so by
> > > not enabling h2 on RSA certificates, we basically disable H2 for
> > > Chrome on Windows XP (Chrome using Microsoft's schannel supporting
> > > only RSA on XP). Chrome on Windows Vista would still be broken (as
> > > schannel on Vista supports ECC certificates), but the market share of
> > > Vista is probably negligible. This should help those that cannot break
> > > this unsupported browser/OS combination and still want to use H2. It's
> > > just a theory though at the moment, I need to test it.
> >
> > I like the idea very much! That's indeed something that could be
> > interesting to study. I even think there's nothing about it that
> > cannot be done with 1.0.2, it would deserve a test!
>
> I tried it and it works fine, crt-list looking like this:
> /etc/private/ssl/sitecert-rsa.pem [alpn http/1.1]
> /etc/private/ssl/sitecert-ecc.pem [alpn h2,http/1.1]
>
> However, openssl 1.1.1 (or boringssl) is required for this, also see
> commit 84e417d85934 ("MINOR: ssl: support Openssl 1.1.1 early callback
> for switchctx"). I doubt this can be done with older openssl.

Ah, I guess it's related to the fact that both carry the same name and
only differ by the key algorithm. Anyway that's a very interesting
approach, I think it would be worth writing an article about it
somewhere.

Cheers,
Willy
Sorry, only registered users may post in this forum.

Click here to login