Repository: go
Issue: net/http,x/crypto/ssh: Hijack hangs when underlying net.Conn doesn't support SetReadDeadline
Labels: NeedsInvestigation

### Go version

go version go1.22.2 linux/amd64

### Output of `go env` in your module/workspace:

```shell
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/fas/.cache/go-build'
GOENV='/home/fas/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/fas/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/fas/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/snap/go/10585'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/snap/go/10585/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.22.2'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/home/fas/github.com/fasmide/the-thing-about-websockets-and-ssh-tunnels/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build565532914=/tmp/go-build -gno-record-gcc-switches'
```


### What did you do?

I was trying to have a web server forwarded through an SSH tunnel - I've made an example of this bug in [fasmide/the-thing-about-websockets-and-ssh-tunnels](https://github.com/fasmide/the-thing-about-websockets-and-ssh-tunnels)

This all works out really well until web sockets are introduced. 

This is because the [http.response, which does Hijacking](https://github.com/golang/go/blob/master/src/net/http/server.go#L2105), tries to set its [net.Conn's deadline to the past](https://github.com/golang/go/blob/master/src/net/http/server.go#L720) to have it unblock its current Read() - but [x/crypto/ssh's implementation of net.Conn](https://github.com/golang/crypto/blob/master/ssh/tcpip.go#L499) does not support this. 

Furthermore, the http.response does not do any error checking when setting the deadline - so effectively the conn locks up without any indication to anyone about whats going on.

### What did you see happen?

Using the example, one should find that using a local net.Listener — everything is fine; however, forwarding the listener through SSH tunnel's, the browser (both Chrome and Firefox) hangs indefinitely trying to connect.

Example of a working local listener:
```
the-thing-about-websockets-and-ssh-tunnels $  go run main.go -local
2024/05/03 10:44:29 *net.TCPListener listening on [::]:13337
```
When opening the webpage, look in the debugger for messages:
![image](https://github.com/golang/go/assets/1194937/af1fc215-a345-4015-baaa-116a84466814)

Example of a broken forwarded listener:
```
the-thing-about-websockets-and-ssh-tunnels $  go run main.go 127.0.0.1:22
2024/05/03 10:46:39 *ssh.tcpListener listening on 127.0.0.1:13337
```
Now, when opening the same webpage, the websocket is stuck in `(pending)`:
![image](https://github.com/golang/go/assets/1194937/03447de5-166c-449c-b98b-8f79587b482d)


### What did you expect to see?

I did not expect there to be any differences :)

I don't know if this bug is in net/http or x/crypto/ssh - but given that HTTP hijack'ing usually returns an error if it is unable to hijack a connection, I would imagine some error checking is to be expected in [net/http when SetReadDeadline returns an error](https://github.com/golang/go/blob/master/src/net/http/server.go#L727)