Disabling HTTP/2 causes client errors
wojtekmach opened this issue · 7 comments
Hey, I'm not sure if it's a bug or I'm misunderstanding things. We're adding ALPN support to Finch and I wanted to test it against a web server without HTTP/2.
In the following snippet I'm using Mint with protocols: [:http1, :http2]
against Bandit with http_2_options: [enabled: false]
:
Mix.install([
:mint,
:bandit
])
defmodule Main do
def main do
unless File.exists?("selfsigned.pem") do
File.write!("selfsigned.pem", """
-----BEGIN CERTIFICATE-----
MIICzjCCAbYCCQDM0i9xf9D8qTANBgkqhkiG9w0BAQsFADApMQswCQYDVQQGEwJJ
VDELMAkGA1UECAwCUk0xDTALBgNVBAcMBFJvbWUwHhcNMTcxMjI4MTAzMTE1WhcN
MTgxMjI4MTAzMTE1WjApMQswCQYDVQQGEwJJVDELMAkGA1UECAwCUk0xDTALBgNV
BAcMBFJvbWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6lBy3mpfB
UrtclV/PFOM8OGiBNYVZmNJmZqCZCl2LQE5ekPrJ2Fh+zkcJcO19OxmseN+2F7VT
zCYarty+h5ZXzNUmUcI2Ld60mfYwEfMjQRa4Tmp0K5PkphJ2gG9n9QOhFxky7KWz
C84oe7Zm8iGni6wAQEEBOdo/qTCfGbPHzd39WUV+9Aft8HeDUcnpMhO6vXWDT3Yh
658p04rXLzj8auyAZpfSq61x9ZS4WQYWB5vRLsJ4/V51RVGfA5nJYFKJ+cwZR4Hz
bTRVc34rXaZS9ggIp8ktqL14NO6jfo9/dRng4RcTmkKMxU+0pWdTNZ7iPJX46/xM
0XGxEd+7X4uHAgMBAAEwDQYJKoZIhvcNAQELBQADggEBABygqnZTQ4dsd5EFQKF7
UT7ZfKi9a65e+iDGHikhUjHc+hSUMXFyP5RjpN6Z+4igi9LuWhJFZ0dqSZxDwCYG
RdrMZSM/2yTBLKVdgcKXPuiV5eFPXHmYm39ru/WpNEqR/P28Q50xz/HJRoFhg3Qe
AIlncG+v6AaUAKD8Qj6IZOLIVJuMaT8ONsDaa2LJiAz5uzKwgijEWiw7m83dvqGi
FHkrj9/l5SQQVLGej/74Av+OFmMRI6nPc5lIu39atMRxsiPubrcQOVZmXZxRSEg8
P7k3nBjtxCUhAnokjRqv/4rYfm8hvbqiRnL3rmtLlM1IF2L37nOqnfGo2NikjV+G
1hU=
-----END CERTIFICATE-----
""")
end
unless File.exists?("selfsigned_key.pem") do
File.write!("selfsigned_key.pem", """
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6lBy3mpfBUrtc
lV/PFOM8OGiBNYVZmNJmZqCZCl2LQE5ekPrJ2Fh+zkcJcO19OxmseN+2F7VTzCYa
rty+h5ZXzNUmUcI2Ld60mfYwEfMjQRa4Tmp0K5PkphJ2gG9n9QOhFxky7KWzC84o
e7Zm8iGni6wAQEEBOdo/qTCfGbPHzd39WUV+9Aft8HeDUcnpMhO6vXWDT3Yh658p
04rXLzj8auyAZpfSq61x9ZS4WQYWB5vRLsJ4/V51RVGfA5nJYFKJ+cwZR4HzbTRV
c34rXaZS9ggIp8ktqL14NO6jfo9/dRng4RcTmkKMxU+0pWdTNZ7iPJX46/xM0XGx
Ed+7X4uHAgMBAAECggEAW+VNi6UJ778m5z/vU5iPH38NAe7xgiLCJouPuDEhx89h
ijRQQZBcbgB9fonvfwnX6FoUnaRpvB9F+Uh9Ex7HDvGlXl1Qkczf7wYR+rUskwWh
AiAlUJiSHEErwNAbjxFfuz0cPTfPmTNMVCYyvduudc5WZj0/hzIOa+KSPxqysMq+
kVEuoKm4yzVpbsvfVjGFhYyetFfqbURZ1d0EONGNiYCtwVPTP+gvcjeMTdgGMno4
cpPHFF5RYsfnG/koaARHbOBtFrnkERpmABfsSL6DzwWtQys/ghxwaL2ZhjhdgbXO
9vjstnXso9mjCAxVZaATyCs6QKXCn//T9BLRkutz+QKBgQDhlwuz2Df7TZwsCOqM
PoYn0GhsY/hHupifEiWvDDtkGCAPuiw48HtCe1aCXFCtbSN/6E3Wdm7ZnG2q7RMY
R5jxEEhnrBGEN7JQhAZPdktndVbupOXMgnGdiz/7nwHPCCghr3X/mdPWY0isMqx/
T7Bl1bv2C5ipOAqHUER7AKd6awKBgQDTus7n3mwYQusGBqhygmpqOr/5JmTjOcFb
fGbyuOE9JntLSGR6mJhlfOYQiESvFhBZEOtw4eDh/n7r8LnV48x6D009466hBY3+
Fs5jTq+Ah2a9gxCRhSfUdEXhrJct+YHEjI+BNvXlUs/2D/y3rvc/2f+qa6nzegTI
1NcmtlEyVQKBgE2dPjV+KqSXqyerWacuy9Fe7s58BqwHEwOHptd3CegCNOW0VAqz
EnVpIfZv9IH2jsQvFLi4vqK4IzMvpeYwm/o0c/TXSp+G2h7BjbpBJOhPgr1Qlo+q
QZTGmBjmOCUW1VfhmmN6dVvJhPNZ6+dRb4tZ4fVhQADYeybbAvSe4QBJAoGAbn1V
6/pOPnrtWr+ut9MG5VizRbmbfFhvZuaMcq24HMkwHiExDikDnjKHfKkf7p58+X2y
372ANW8xnL6Ku+uckTXbASkHwE+9wZL1MS2muFPwcYUr6ESsfFoQ/aurWPqTlZYk
bTHZMEr+61F8d/5+WHvSx4RXtA9A3+zyOel6heECgYEAxqgiod1asd9g6Ao0vQ5Q
YIQihF9Qq15stxj5H0qnBskvDKwS+He8GKjMUJjJss0gD43KCYhRvE8bmMD+rgVJ
oy8Hp5oGeMVUHMG7ly8vdAj01RWxU2oIL5wlk3hX+4Pb6XyAN+NuCTMCQ8XukfTf
AyfpMLycjN7uWN86CdTv/YY=
-----END PRIVATE KEY-----
""")
end
defmodule MyPlug do
def init(options) do
options
end
def call(conn, _) do
{adapter, _} = conn.adapter
Plug.Conn.send_resp(conn, 200, inspect(adapter))
end
end
{:ok, _} =
Bandit.start_link(
scheme: :https,
port: 4000,
plug: MyPlug,
certfile: Path.expand("selfsigned.pem"),
keyfile: Path.expand("selfsigned_key.pem"),
http_2_options: [enabled: false]
)
{:ok, conn} =
Mint.HTTP.connect(:https, "localhost", 4000,
transport_opts: [
verify: :verify_none
],
mode: :passive,
protocols: [:http1, :http2]
)
case Mint.HTTP.request(conn, "GET", "/", [], "") do
{:ok, _conn, ref} ->
IO.inspect(ref)
{:error, _conn, exception} ->
raise exception
end
end
end
Main.main()
It raises:
15:48:24.913 [info] Running Main.MyPlug with Bandit 1.1.0 at 0.0.0.0:4000 (https)
** (Mint.TransportError) socket closed
req.exs:99: Main.main/0
req.exs:104: (file)
Running curl against this server:
$ curl --insecure -v http://localhost:4000
* Trying 127.0.0.1:4000...
* Connected to localhost (127.0.0.1) port 4000 (#0)
> GET / HTTP/1.1
> Host: localhost:4000
> User-Agent: curl/8.1.2
> Accept: */*
>
* Received HTTP/0.9 when not allowed
* Closing connection 0
curl: (1) Received HTTP/0.9 when not allowed
What names are you using within ALPN for the protocols? Bandit expects either h2
or http/1.1
per https://github.com/mtrudel/bandit/blob/main/lib/bandit/initial_handler.ex#L50-L51
The 'received HTTP/0.9` suggests to me that Bandit is erroring out and sending a fallback 400 response to the client. Do you have any logs on the server side? I'd expect Bandit to be noisy in any case.
About curl, sorry, user error. I was using http instead of https. For http:// bandit indeed printed:
16:09:44.954 [notice] TLS :server: In state :hello at tls_record.erl:561 generated SERVER ALERT: Fatal - Unexpected Message
- {:unsupported_record_type, 71}
Still getting curl error for https:// though:
$ curl --insecure -v https://localhost:4000
* Trying 127.0.0.1:4000...
* Connected to localhost (127.0.0.1) port 4000 (#0)
* ALPN: offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256
* ALPN: server accepted h2
* Server certificate:
* subject: C=IT; ST=RM; L=Rome
* start date: Dec 28 10:31:15 2017 GMT
* expire date: Dec 28 10:31:15 2018 GMT
* issuer: C=IT; ST=RM; L=Rome
* SSL certificate verify result: self signed certificate (18), continuing anyway.
* using HTTP/2
* h2 [:method: GET]
* h2 [:scheme: https]
* h2 [:authority: localhost:4000]
* h2 [:path: /]
* h2 [user-agent: curl/8.1.2]
* h2 [accept: */*]
* Using Stream ID: 1 (easy handle 0x124813800)
> GET / HTTP/2
> Host: localhost:4000
> User-Agent: curl/8.1.2
> Accept: */*
>
* Closing connection 0
curl: (56) Failure when receiving data from the peer
regarding ALPN, Mint seems to be using correct values: https://github.com/elixir-mint/mint/blob/v1.5.1/lib/mint/negotiate.ex#L14.
Curious. Let me try and repro here.
I see it.
The initial handler is seeing an ALPN protocol of h2
, but because we're not configured to accept HTTP/2 it's closing the connection here.
The actual problem is that we're still registering h2
support here, when we should be only registering the actually supported protocols.
I'll get a fix up for this right away
PR is up - testing locally shows that our ALPN advertisements are as expected
Published as 1.1.1