* Found bundle for host localhost: 0x55940b5fcab0 [serially]
* Server doesn't support multiplex yet, wait
* No connections available.
DL% UL% Dled Uled Xfers Live Qd Total Current Left Speed
-- -- 0 0 2 2 0 --:--:-- --:--:-- --:--:-- -9223 * Trying ::1:8443...
* Connected to localhost (::1) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: none
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [122 bytes data]
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
{ [15 bytes data]
* TLSv1.3 (IN), TLS handshake, Certificate (11):
{ [1404 bytes data]
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
{ [520 bytes data]
* TLSv1.3 (IN), TLS handshake, Finished (20):
{ [52 bytes data]
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.3 (OUT), TLS handshake, Finished (20):
} [52 bytes data]
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd
* start date: Apr 7 13:04:05 2021 GMT
* expire date: Apr 7 13:04:05 2022 GMT
* issuer: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd
* 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
} [5 bytes data]
* Using Stream ID: 1 (easy handle 0x55940b609d10)
} [5 bytes data]
> GET /largefile HTTP/2
> Host: localhost:8443
> user-agent: curl/7.76.0-DEV
> accept: */*
>
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ [265 bytes data]
* Found bundle for host localhost: 0x55940b5fcab0 [can multiplex]
* Multiplexed connection found!
* Re-using existing connection! (#0) with host localhost
* Transfer was pending, now try another
* Using Stream ID: 3 (easy handle 0x55940b60b1a0)
} [5 bytes data]
> GET /secure HTTP/2
> Host: localhost:8443
> user-agent: curl/7.76.0-DEV
> accept: */*
>
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ [265 bytes data]
* old SSL session ID is stale, removing
{ [5 bytes data]
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
} [5 bytes data]
< HTTP/2 200
< date: Wed, 07 Apr 2021 13:51:32 GMT
< server: Apache/2.4.46 (Unix) OpenSSL/1.1.1d
< last-modified: Wed, 07 Apr 2021 13:51:15 GMT
< etag: "40000000-5bf6239719ac0"
< accept-ranges: bytes
< content-length: 1073741824
<
{ [1154 bytes data]
* Connection died, retrying a fresh connect(retry count: 1)
* Issue another request to this URL: 'https://localhost:8443/secure'
* Found bundle for host localhost: 0x55940b5fcab0 [can multiplex]
* Hostname localhost was found in DNS cache
* Trying ::1:8443...
* Transfer was pending, now try another
* Connected to localhost (::1) port 8443 (#1)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: none
* SSL re-using session ID
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [631 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [128 bytes data]
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
{ [15 bytes data]
* TLSv1.3 (IN), TLS handshake, Finished (20):
{ [52 bytes data]
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.3 (OUT), TLS handshake, Finished (20):
} [52 bytes data]
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd
* start date: Apr 7 13:04:05 2021 GMT
* expire date: Apr 7 13:04:05 2022 GMT
* issuer: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd
* 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
} [5 bytes data]
* Using Stream ID: 1 (easy handle 0x55940b60b1a0)
} [5 bytes data]
> GET /secure HTTP/2
> Host: localhost:8443
> user-agent: curl/7.76.0-DEV
> accept: */*
>
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ [265 bytes data]
* old SSL session ID is stale, removing
{ [5 bytes data]
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
} [5 bytes data]
* HTTP/2 stream 0 was not closed cleanly: HTTP_1_1_REQUIRED (err 13)
* Downgrades to HTTP/1.1!
* Empty reply from server
* Closing connection 1
} [5 bytes data]
* TLSv1.3 (OUT), TLS alert, close notify (256):
} [2 bytes data]
* Issue another request to this URL: 'https://localhost:8443/secure'
* Found bundle for host localhost: 0x55940b5fcab0 [can multiplex]
* Hostname localhost was found in DNS cache
* Trying ::1:8443...
* Transfer was pending, now try another
* Connected to localhost (::1) port 8443 (#2)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: none
* SSL re-using session ID
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [628 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [128 bytes data]
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
{ [21 bytes data]
* TLSv1.3 (IN), TLS handshake, Finished (20):
{ [52 bytes data]
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.3 (OUT), TLS handshake, Finished (20):
} [52 bytes data]
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd
* start date: Apr 7 13:04:05 2021 GMT
* expire date: Apr 7 13:04:05 2022 GMT
* issuer: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd
* SSL certificate verify result: self signed certificate (18), continuing anyway.
} [5 bytes data]
> GET /secure HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/7.76.0-DEV
> Accept: */*
>
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ [265 bytes data]
* old SSL session ID is stale, removing
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Request CERT (13):
{ [77 bytes data]
* TLSv1.3 (OUT), TLS handshake, Certificate (11):
} [40 bytes data]
* TLSv1.3 (OUT), TLS handshake, Finished (20):
} [52 bytes data]
* TLSv1.3 (IN), TLS alert, unknown (628):
{ [2 bytes data]
* OpenSSL SSL_read: error:1409445C:SSL routines:ssl3_read_bytes:tlsv13 alert certificate required, errno 0
* Closing connection 2
curl: (56) Empty reply from server
{ [5 bytes data]
23 -- 237M 0 2 1 0 0:00:02 --:--:-- 0:00:01 474M
47 -- 489M 0 2 1 0 0:00:02 0:00:01 0:00:01 488M
I did this
We have a server, where some endpoints require TLS client cert authentication. As HTTP/2 does not support TLS renegotiation, when this endpoint is called, the server replies with
HTTP_1_1_REQUIREDand a new connection is necessary.In curl 7.76.0, there was a fix for the simplest case by closing the connection: #6793
However, if there is another multiplexed connection which uses the same HTTP/2 connection, this solution does not work.
To reproduce with an Apache server, use the following
Dockerfile:If this
Dockerfileis saved to an empty directory, run the following command in that directory to start the server:When the server is running, call curl with:
Around 50% of the time on my machine (but it's timing dependant, the size of the
largefilemight need to be modified in theDockerfileabove) the call is retried over HTTP/2.Click here for example curl output when it went wrong!
I expected the following
Curl should have retried the connection via HTTP/1.1, but it's retried with HTTP/2. It seems like that the HTTP/2 connection can stay in the pool (which is actually not a problem because further requests might be able to use that), and when that happen, the retry is done over HTTP/2. I think the proper solution would be to check the wanted HTTP version when choosing a connection to re-use.
curl/libcurl version
I've compiled curl from the 7.76 tag (https://github.com/curl/curl/tree/curl-7_76_0)
operating system