New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use HTTP2-compatible cipher as first preference #406
Conversation
By listing ECDHE-RSA-AES128-GCM-SHA256 as the first preference, HTTP2 servers will always either pick that or their own preference, which is not blacklisted by the HTTP2 spec.
related nghttp2/nghttp2#140 I don't like your fix, why wouldn't we want to sort by strength? Isn't the issue here that the server chokes on the cipher? Even if it's prohibited so what, shouldn't the server just pick another one? Does blacklisted mean obligatory choke? And is there some departure here from HTTPS where the server has the final say? I don't know much about HTTP2. FWIW in Windows OpenSSL 1.0.2d 9 Jul 2015 I get the same cipher list regardless of whether or not I use |
FYI: This is a change in the golang.org server too, I verified my fix against their server at the time I wrote it. It worked then. |
So let me try to understand. We offer a list of ciphers in our preferred order (sorted by strength as we see it). We don't know if the server will speak h1 or h2 so we can't simply use two separate lists. The server picks the one to use in the TLS handshake - the same handshake that also makes the server select to speak h2. A few milliseconds later, it rejects the cipher suite it selected on the basis that it isn't a valid HTTP/2 cipher suite... Or did I misunderstand anything here? |
Section 9.2.2 in RFC 7540 explains exactly this situation: "Note that clients might advertise support of cipher suites that are on the black list in order to allow for connection to servers that do not support HTTP/2. This allows servers to select HTTP/1.1 with a cipher suite that is on the HTTP/2 black list. However, this can result in HTTP/2 being negotiated with a black-listed cipher suite if the application protocol and cipher suite are independently selected." Tricky. |
Yes. The golang HTTP2 server takes the first implemented (but possibly blacklisted) client's cipher preference by default. In my opinion the HTTP2 spec is very weak here:
The workaround is to set
However, that's still not enough. (cc @bradfitz) |
Still, I added "@strength" there for one primary reason - to make it work with the golang server. I realize we need to be pragmatic and go where things work, just pointing out some facts. |
So yes, other people are also telling me that "@strength" doesn't work and that we need to list ciphers explicitly. Let's bite the bullet. Any suggestions? |
Second line, with verification: $ docker run --read-only=true -ti --rm wmark/curl --http2 -v --head https://http2.golang.org/
…
* Cipher selection: EECDH+HIGH+TLSv1.2:EECDH+HIGH:EDH+HIGH+TLSv1.2:-AES256:HIGH:-3DES:!aNULL:!eNULL:!RC4
…
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
… In case you don't want to demote AES256 and risk more of unsuitable pairings such as (P256, AES256):
By the way, there is at least one CL for Golang to include SHA384 as hash for TLS. My patch is not the first one: |
But what about the EXPORT ones and LOW that are disabled in the existing set? Shouldn't we then rather do something like:
|
HIGH and EXPORTxx are disjoint sets as far as I can check (OpenSSL 1.0.1, 1.0.2; and BoringSSL). |
Thanks. I thought about it some more, and since TLS 1.2 wasn't added in openssl until 1.0.1 I think a safer version would be like below, which keeps the previous version for really old versions. Thoughts?
|
I don't understand why it is our problem if the protocol and cipher are independently selected by the server. Shouldn't the responsibility be on them? They're the ones selecting the bad cipher. I filed at golang/go#12895, let's see what happens. |
Go HTTP/2 server is now accessible via curl HTTP/2 regardless of client cipher order thanks to @bradfitz. When this was up in the air I wrote a script to generate an HTTP/2 blacklisted cipher check in C. I also experimented with deprioritizing HTTP/2 blacklisted ciphers. Fortunately we do not need to do this now, afaict, but I've released it for reference in case we need to revisit this in the future. Any objections to closing this? |
This is a follow up of https://sourceforge.net/p/curl/bugs/1487/ - 0d1060f did not solve this issue for me.
When connecting to http2.golang.org, OpenSSL advertises the following cipher suites after sorting ciphers with
@STRENGTH
:The go server apparently does not support
SHA384
. As a consequence,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
will be picked, which is blacklisted by the HTTP2 spec. This causes the go server to fail the connection.By listing ECDHE-RSA-AES128-GCM-SHA256 as the first preference, HTTP2 servers will always either pick that (HTTP2 servers must implement that cipher according to the spec) or the server preference, which should not be blacklisted by the HTTP2 spec. Unfortunately,
ECDHE-RSA-AES128-GCM-SHA256
is considered to be weaker by OpenSSL (AES128
vsAES256
I suppose), so we need to remove@STRENGTH
again.Test case:
curl --http2 https://http2.golang.org/