Skip to content

HTTP/2 over HTTPS has a problem, but HTTP/1.1 over HTTPS does not #141

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

Closed
nwtgck opened this issue Jan 6, 2021 · 8 comments
Closed

HTTP/2 over HTTPS has a problem, but HTTP/1.1 over HTTPS does not #141

nwtgck opened this issue Jan 6, 2021 · 8 comments

Comments

@nwtgck
Copy link
Contributor

nwtgck commented Jan 6, 2021

Hi. Thank you for your wonderful project!

I upgrade hyper to 0.14 and hyper-rustls from 0.14 to 0.22. Then, I got an error only on HTTP/2 over HTTPS.

How to reproduce the error?

I created a minimal sample here:

Type the following commands to run an HTTPS server.

git clone [email protected]:nwtgck/public-code.git
cd public-code/hyper-0-14-http2-unexpected-eof-problem
cargo run

Then, https://localhost:8443/ is served.

I got "hello, world" successfully when using HTTP/1.1 over HTTPS like the following.

$ curl -k --http1.1 https://localhost:8443/
hello, world

But, I got an error when using HTTP/2 over HTTPS like the following.

$ curl -k --http2 https://localhost:8443/
curl: (56) Unexpected EOF

Here is verbose output with -vvv.

$ curl -vvvk --http2 https://localhost:8443/
*   Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 8443 failed: Connection refused
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=localhost
*  start date: Jan  6 15:33:09 2021 GMT
*  expire date: Jan  6 15:33:09 2022 GMT
*  issuer: CN=localhost
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fadb080d800)
> GET / HTTP/2
> Host: localhost:8443
> User-Agent: curl/7.54.0
> Accept: */*
>
* Unexpected EOF
* Closing connection 0
* TLSv1.2 (OUT), TLS alert, Client hello (1):
curl: (56) Unexpected EOF

I got an error in Web browser too. Honestly speaking, I am not sure which library causes the error: tokio, hyper, tokio-rustls, rustls, hyper-rustls, so I may post the issue on wrong place.

When I used like the following dependencies with hyper 0.13 and the same rust code, HTTP/2 over HTTPS worked as I expected.

# <hyper 0.13 (old)>
# ...

[dependencies]
hyper = { version = "0.13", features = ["stream"] }
futures = "0.3"
http = "0.2"
tokio = { version = "0.2", features = ["macros", "stream"] }
rustls = "0.18"
hyper-rustls = "0.22"
futures-util = "0.3"
tokio-rustls = "0.14"
async-stream = "0.3.0"
@paolobarbolini
Copy link
Contributor

paolobarbolini commented Jan 6, 2021

Can you try enabling both the http1 and http2 feature of hyper?

Hyper 0.14 doesn't enable HTTP/1 and HTTP/2 support by default, but hyper-rustls enables the http1 feature (change introduced in #135), in order to get access to the hyper http connection types.
The issue with it is that ALPN is always handled (see #139 (comment)), so that might cause some issues with the client if http2 isn't enabled in hyper.

@nwtgck
Copy link
Contributor Author

nwtgck commented Jan 6, 2021

Thanks for the reply.

Can you try enabling both the http1 and http2 feature of hyper?

I think I enabled both: https://github.com/nwtgck/public-code/blob/4e41b1801f1a44357cb9af8824b06083c72d5e64/hyper-0-14-http2-unexpected-eof-problem/Cargo.toml#L10

@paolobarbolini
Copy link
Contributor

paolobarbolini commented Jan 6, 2021

Try using http2 instead of h2

@nwtgck
Copy link
Contributor Author

nwtgck commented Jan 6, 2021

Thanks. It solved the issue!

@nwtgck nwtgck closed this as completed Jan 6, 2021
@nwtgck
Copy link
Contributor Author

nwtgck commented Jan 6, 2021

Here is the successful result with -vvv for future visitors.

$ curl -vvv -k --http2 https://localhost:8443/
*   Trying ::1...
* TCP_NODELAY set
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=localhost
*  start date: Jan  6 15:33:09 2021 GMT
*  expire date: Jan  6 15:33:09 2022 GMT
*  issuer: CN=localhost
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fa406806600)
> GET / HTTP/2
> Host: localhost:8443
> User-Agent: curl/7.54.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200
< date: Wed, 06 Jan 2021 17:46:17 GMT
< content-length: 13
<
hello, world
* Connection #0 to host localhost left intact

@Rutik7066
Copy link

Can you try enabling both the http1 and http2 feature of hyper?

Hyper 0.14 doesn't enable HTTP/1 and HTTP/2 support by default, but hyper-rustls enables the http1 feature (change introduced in #135), in order to get access to the hyper http connection types. The issue with it is that ALPN is always handled (see #139 (comment)), so that might cause some issues with the client if http2 isn't enabled in hyper.

isn't it possible to use only http2 without ssl

@djc
Copy link
Member

djc commented Jan 18, 2024

In general, no, HTTP/2 is commonly only deployed with TLS enabled.

@winstxnhdw
Copy link

In general, no, HTTP/2 is commonly only deployed with TLS enabled.

I believe this is not part of the standard: https://http2.github.io/faq/

Hyper should support HTTP/2 regardless.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants