Skip to content
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

net/http,x/crypto/ssh: Hijack hangs when underlying net.Conn doesn't support SetReadDeadline #67152

Open
fasmide opened this issue May 3, 2024 · 2 comments
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.

Comments

@fasmide
Copy link

fasmide commented May 3, 2024

Go version

go version go1.22.2 linux/amd64

Output of go env in your module/workspace:

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

This all works out really well until web sockets are introduced.

This is because the http.response, which does Hijacking, tries to set its net.Conn's deadline to the past to have it unblock its current Read() - but x/crypto/ssh's implementation of net.Conn 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

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

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

@seankhliao seankhliao changed the title net/http - x/crypto/ssh: golang cant do websockets in ssh tunnels net/http,x/crypto/ssh: Hijack hangs when underlying net.Conn doesn't support SetReadDeadline May 3, 2024
@seankhliao seankhliao added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label May 3, 2024
@adrianosela
Copy link

Big ➕1 on this one... I have an HTTP reverse proxy (i.e. httputil.ReverseProxy ) behind an SSH tunnel. Can't do WebSockets over that because the ssh Conn does not support deadlines....

It seems to me like adding setting/checking deadlines to the SSH channel objects (i.e. here) wouldn't be too hard?

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/562756 mentions this issue: ssh: add deadlines support for channels

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

4 participants