-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
What version of Go are you using (go version)?
$ go version go version go1.19.4 darwin/amd64
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (go env)?
Darwin / ARM64 / AMD64, but also reproduced on Linux / AMD64.
What did you do?
Run the following code with server that completes TLS handshake, but then just sends random raw data.
In other words, our client never receives frame with flags=END_STREAM.
func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(3*time.Second))
defer cancel()
cl := &http.Client{Timeout: 3 * time.Second}
req, _ := http.NewRequestWithContext(ctx, "GET", os.Args[1], nil)
cl.Do(req)
}What did you expect to see?
After 3 seconds, the connection is aborted.
What did you see instead?
The connection hangs indefinitely.
Additional Context
We've seen this happen with Cloudflare in front of a non-http(s) backend.
In this case we assume it is wrongly configured to point at a SSH daemon.
Even in that case, we should not hang forever.
Running with GODEBUG=http2debug=2:
2023/01/17 19:17:30 http2: Transport failed to get client conn for <snip>:443: http2: no cached connection was available
2023/01/17 19:17:30 http2: Transport creating client conn 0xc0000a8180 to [<snip>]:443
2023/01/17 19:17:30 http2: Framer 0xc0000e0460: wrote SETTINGS len=18, settings: ENABLE_PUSH=0, INITIAL_WINDOW_SIZE=4194304, MAX_HEADER_LIST_SIZE=10485760
2023/01/17 19:17:30 http2: Framer 0xc0000e0460: wrote WINDOW_UPDATE len=4 (conn) incr=1073741824
2023/01/17 19:17:30 http2: Transport encoding header ":authority" = "<snip>"
2023/01/17 19:17:30 http2: Transport encoding header ":method" = "GET"
2023/01/17 19:17:30 http2: Transport encoding header ":path" = "/"
2023/01/17 19:17:30 http2: Transport encoding header ":scheme" = "https"
2023/01/17 19:17:30 http2: Transport encoding header "accept-encoding" = "gzip"
2023/01/17 19:17:30 http2: Transport encoding header "user-agent" = "Go-http-client/2.0"
2023/01/17 19:17:30 http2: Framer 0xc0000e0460: wrote HEADERS flags=END_STREAM|END_HEADERS stream=1 len=39
2023/01/17 19:17:30 http2: Framer 0xc0000e0460: read SETTINGS len=18, settings: MAX_CONCURRENT_STREAMS=256, INITIAL_WINDOW_SIZE=65536, MAX_FRAME_SIZE=16777215
2023/01/17 19:17:30 http2: Transport received SETTINGS len=18, settings: MAX_CONCURRENT_STREAMS=256, INITIAL_WINDOW_SIZE=65536, MAX_FRAME_SIZE=16777215
2023/01/17 19:17:30 http2: Framer 0xc0000e0460: wrote SETTINGS flags=ACK len=0
2023/01/17 19:17:30 http2: Framer 0xc0000e0460: read WINDOW_UPDATE len=4 (conn) incr=2147418112
2023/01/17 19:17:30 http2: Transport received WINDOW_UPDATE len=4 (conn) incr=2147418112
2023/01/17 19:17:30 http2: Framer 0xc0000e0460: read SETTINGS flags=ACK len=0
2023/01/17 19:17:30 http2: Transport received SETTINGS flags=ACK len=0
2023/01/17 19:17:30 http2: Framer 0xc0000e0460: read HEADERS flags=END_HEADERS stream=1 len=417
2023/01/17 19:17:30 http2: decoded hpack field header field ":status" = "101"
2023/01/17 19:17:30 http2: decoded hpack field header field "date" = "Tue, 17 Jan 2023 18:17:31 GMT"
2023/01/17 19:17:30 http2: decoded hpack field header field "cf-cache-status" = "DYNAMIC"
2023/01/17 19:17:30 http2: decoded hpack field header field "report-to" = "{\"endpoints\":[{\"url\":\"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=<snip>\"}],\"group\":\"cf-nel\",\"max_age\":604800}"
2023/01/17 19:17:30 http2: decoded hpack field header field "nel" = "{\"success_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}"
2023/01/17 19:17:30 http2: decoded hpack field header field "server" = "cloudflare"
2023/01/17 19:17:30 http2: decoded hpack field header field "cf-ray" = "78b116903a38731a-LHR"
2023/01/17 19:17:30 http2: decoded hpack field header field "alt-svc" = "h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400"
2023/01/17 19:17:30 http2: Transport received HEADERS flags=END_HEADERS stream=1 len=417
2023/01/17 19:17:30 http2: Framer 0xc0000e0460: read DATA stream=1 len=41 data="SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5\r\n"
2023/01/17 19:17:30 http2: Transport received DATA stream=1 len=41 data="SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5\r\n"
x/net/http2 also provides a ReadIdleTimeout and PingTimeout. According to the docs:
ReadIdleTimeout is the timeout after which a health check using ping frame will be carried out if no frame is received on the connection.
PingTimeout is the timeout after which the connection will be closed if a response to Ping is not received.
So the following was tried:
func main() {
t2 := &http2.Transport{
ReadIdleTimeout: 3 * time.Second,
PingTimeout: 1 * time.Second,
}
cl := &http.Client{Transport: t2}
req, _ := http.NewRequest("GET", os.Args[1], nil)
cl.Do(req)
}This still hangs indefinitely.