Description
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:
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)
:
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