
Some checks failed
checklocks / checklocks (push) Waiting to run
CodeQL / Analyze (go) (push) Waiting to run
Dockerfile build / deploy (push) Waiting to run
CI / race-root-integration (1/4) (push) Waiting to run
CI / race-root-integration (2/4) (push) Waiting to run
CI / race-root-integration (3/4) (push) Waiting to run
CI / race-root-integration (4/4) (push) Waiting to run
CI / test (-coverprofile=/tmp/coverage.out, amd64) (push) Waiting to run
CI / test (-race, amd64, 1/3) (push) Waiting to run
CI / test (-race, amd64, 2/3) (push) Waiting to run
CI / test (-race, amd64, 3/3) (push) Waiting to run
CI / test (386) (push) Waiting to run
CI / windows (push) Waiting to run
CI / privileged (push) Waiting to run
CI / vm (push) Waiting to run
CI / race-build (push) Waiting to run
CI / cross (386, linux) (push) Waiting to run
CI / cross (amd64, darwin) (push) Waiting to run
CI / cross (amd64, freebsd) (push) Waiting to run
CI / cross (amd64, openbsd) (push) Waiting to run
CI / cross (amd64, windows) (push) Waiting to run
CI / cross (arm, 5, linux) (push) Waiting to run
CI / cross (arm, 7, linux) (push) Waiting to run
CI / cross (arm64, darwin) (push) Waiting to run
CI / cross (arm64, linux) (push) Waiting to run
CI / cross (arm64, windows) (push) Waiting to run
CI / cross (loong64, linux) (push) Waiting to run
CI / ios (push) Waiting to run
CI / crossmin (amd64, illumos) (push) Waiting to run
CI / crossmin (amd64, plan9) (push) Waiting to run
CI / crossmin (amd64, solaris) (push) Waiting to run
CI / crossmin (ppc64, aix) (push) Waiting to run
CI / android (push) Waiting to run
CI / wasm (push) Waiting to run
CI / tailscale_go (push) Waiting to run
CI / fuzz (push) Waiting to run
CI / depaware (push) Waiting to run
CI / go_generate (push) Waiting to run
CI / go_mod_tidy (push) Waiting to run
CI / licenses (push) Waiting to run
CI / staticcheck (386, windows) (push) Waiting to run
CI / staticcheck (amd64, darwin) (push) Waiting to run
CI / staticcheck (amd64, linux) (push) Waiting to run
CI / staticcheck (amd64, windows) (push) Waiting to run
CI / notify_slack (push) Blocked by required conditions
CI / check_mergeability (push) Blocked by required conditions
update-flake / update-flake (push) Has been cancelled
The upstream crypto package now supports sending banners at any time during authentication, so the Tailscale fork of crypto/ssh is no longer necessary. github.com/tailscale/golang-x-crypto is still needed for some custom ACME autocert functionality. tempfork/gliderlabs is still necessary because of a few other customizations, mostly related to TTY handling. Originally implemented in46fd4e58a2
, which was reverted inb60f6b849a
to keep the change out of v1.80. Updates #8593 Signed-off-by: Percy Wegmann <percy@tailscale.com>
86 lines
1.9 KiB
Go
86 lines
1.9 KiB
Go
//go:build glidertests
|
|
|
|
package ssh
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"net"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
|
|
gossh "golang.org/x/crypto/ssh"
|
|
)
|
|
|
|
var sampleServerResponse = []byte("Hello world")
|
|
|
|
func sampleSocketServer() net.Listener {
|
|
l := newLocalListener()
|
|
|
|
go func() {
|
|
conn, err := l.Accept()
|
|
if err != nil {
|
|
return
|
|
}
|
|
conn.Write(sampleServerResponse)
|
|
conn.Close()
|
|
}()
|
|
|
|
return l
|
|
}
|
|
|
|
func newTestSessionWithForwarding(t *testing.T, forwardingEnabled bool) (net.Listener, *gossh.Client, func()) {
|
|
l := sampleSocketServer()
|
|
|
|
_, client, cleanup := newTestSession(t, &Server{
|
|
Handler: func(s Session) {},
|
|
LocalPortForwardingCallback: func(ctx Context, destinationHost string, destinationPort uint32) bool {
|
|
addr := net.JoinHostPort(destinationHost, strconv.FormatInt(int64(destinationPort), 10))
|
|
if addr != l.Addr().String() {
|
|
panic("unexpected destinationHost: " + addr)
|
|
}
|
|
return forwardingEnabled
|
|
},
|
|
}, nil)
|
|
|
|
return l, client, func() {
|
|
cleanup()
|
|
l.Close()
|
|
}
|
|
}
|
|
|
|
func TestLocalPortForwardingWorks(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
l, client, cleanup := newTestSessionWithForwarding(t, true)
|
|
defer cleanup()
|
|
|
|
conn, err := client.Dial("tcp", l.Addr().String())
|
|
if err != nil {
|
|
t.Fatalf("Error connecting to %v: %v", l.Addr().String(), err)
|
|
}
|
|
result, err := io.ReadAll(conn)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !bytes.Equal(result, sampleServerResponse) {
|
|
t.Fatalf("result = %#v; want %#v", result, sampleServerResponse)
|
|
}
|
|
}
|
|
|
|
func TestLocalPortForwardingRespectsCallback(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
l, client, cleanup := newTestSessionWithForwarding(t, false)
|
|
defer cleanup()
|
|
|
|
_, err := client.Dial("tcp", l.Addr().String())
|
|
if err == nil {
|
|
t.Fatalf("Expected error connecting to %v but it succeeded", l.Addr().String())
|
|
}
|
|
if !strings.Contains(err.Error(), "port forwarding is disabled") {
|
|
t.Fatalf("Expected permission error but got %#v", err)
|
|
}
|
|
}
|