From d3643fa151a4fd011243e786547706b38c579894 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 8 Jun 2022 08:15:16 -0700 Subject: [PATCH] cmd/tailscale: add 'debug ts2021' Noise connectivity subcommand Updates #3488 Change-Id: I9272e68f66c4cf36fb98dd1248a74d3817447690 Signed-off-by: Brad Fitzpatrick --- cmd/tailscale/cli/debug.go | 80 ++++++++++++++++++++++++++++++++++++++ cmd/tailscale/depaware.txt | 22 ++++++----- 2 files changed, 93 insertions(+), 9 deletions(-) diff --git a/cmd/tailscale/cli/debug.go b/cmd/tailscale/cli/debug.go index c23d976af..72ef186fb 100644 --- a/cmd/tailscale/cli/debug.go +++ b/cmd/tailscale/cli/debug.go @@ -15,6 +15,8 @@ import ( "fmt" "io" "log" + "net" + "net/http" "os" "runtime" "strconv" @@ -23,11 +25,14 @@ import ( "github.com/peterbourgon/ff/v3/ffcli" "inet.af/netaddr" + "tailscale.com/control/controlhttp" "tailscale.com/hostinfo" "tailscale.com/ipn" "tailscale.com/net/tsaddr" "tailscale.com/paths" "tailscale.com/safesocket" + "tailscale.com/tailcfg" + "tailscale.com/types/key" ) var debugCmd = &ffcli.Command{ @@ -118,6 +123,17 @@ var debugCmd = &ffcli.Command{ Exec: runVia, ShortHelp: "convert between site-specific IPv4 CIDRs and IPv6 'via' routes", }, + { + Name: "ts2021", + Exec: runTS2021, + ShortHelp: "debug ts2021 protocol connectivity", + FlagSet: (func() *flag.FlagSet { + fs := newFlagSet("ts2021") + fs.StringVar(&ts2021Args.host, "host", "controlplane.tailscale.com", "hostname of control plane") + fs.IntVar(&ts2021Args.version, "version", int(tailcfg.CurrentCapabilityVersion), "protocol version") + return fs + })(), + }, }, } @@ -425,3 +441,67 @@ func runVia(ctx context.Context, args []string) error { } return nil } + +var ts2021Args struct { + host string // "controlplane.tailscale.com" + version int // 27 or whatever +} + +func runTS2021(ctx context.Context, args []string) error { + log.SetOutput(os.Stdout) + log.SetFlags(log.Ltime | log.Lmicroseconds) + + machinePrivate := key.NewMachine() + var dialer net.Dialer + + var keys struct { + PublicKey key.MachinePublic + } + keysURL := "https://" + ts2021Args.host + "/key?v=" + strconv.Itoa(ts2021Args.version) + log.Printf("Fetching keys from %s ...", keysURL) + req, err := http.NewRequestWithContext(ctx, "GET", keysURL, nil) + if err != nil { + return err + } + res, err := http.DefaultClient.Do(req) + if err != nil { + log.Printf("Do: %v", err) + return err + } + if res.StatusCode != 200 { + log.Printf("Status: %v", res.Status) + return errors.New(res.Status) + } + if err := json.NewDecoder(res.Body).Decode(&keys); err != nil { + log.Printf("JSON: %v", err) + return fmt.Errorf("decoding /keys JSON: %w", err) + } + res.Body.Close() + + dialFunc := func(ctx context.Context, network, address string) (net.Conn, error) { + log.Printf("Dial(%q, %q) ...", network, address) + c, err := dialer.DialContext(ctx, network, address) + if err != nil { + log.Printf("Dial(%q, %q) = %v", network, address, err) + } else { + log.Printf("Dial(%q, %q) = %v / %v", network, address, c.LocalAddr(), c.RemoteAddr()) + } + return c, err + } + + conn, err := controlhttp.Dial(ctx, net.JoinHostPort(ts2021Args.host, "80"), machinePrivate, keys.PublicKey, uint16(ts2021Args.version), dialFunc) + log.Printf("controlhttp.Dial = %p, %v", conn, err) + if err != nil { + return err + } + log.Printf("did noise handshake") + + gotPeer := conn.Peer() + if gotPeer != keys.PublicKey { + log.Printf("peer = %v, want %v", gotPeer, keys.PublicKey) + return errors.New("key mismatch") + } + + log.Printf("final underlying conn: %v / %v", conn.LocalAddr(), conn.RemoteAddr()) + return nil +} diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index 8912ff566..638a32120 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -8,7 +8,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/interfaces L github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink github.com/kballard/go-shellquote from tailscale.com/cmd/tailscale/cli - L github.com/klauspost/compress/flate from nhooyr.io/websocket + github.com/klauspost/compress/flate from nhooyr.io/websocket L 💣 github.com/mdlayher/netlink from github.com/jsimonetti/rtnetlink+ L 💣 github.com/mdlayher/netlink/nlenc from github.com/jsimonetti/rtnetlink+ L 💣 github.com/mdlayher/socket from github.com/mdlayher/netlink @@ -31,14 +31,16 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep go4.org/unsafe/assume-no-moving-gc from go4.org/intern W 💣 golang.zx2c4.com/wireguard/windows/tunnel/winipcfg from tailscale.com/net/interfaces+ inet.af/netaddr from tailscale.com/cmd/tailscale/cli+ - L nhooyr.io/websocket from tailscale.com/derp/derphttp - L nhooyr.io/websocket/internal/errd from nhooyr.io/websocket - L nhooyr.io/websocket/internal/xsync from nhooyr.io/websocket + nhooyr.io/websocket from tailscale.com/derp/derphttp+ + nhooyr.io/websocket/internal/errd from nhooyr.io/websocket + nhooyr.io/websocket/internal/xsync from nhooyr.io/websocket tailscale.com from tailscale.com/version tailscale.com/atomicfile from tailscale.com/ipn+ tailscale.com/client/tailscale from tailscale.com/cmd/tailscale/cli+ tailscale.com/client/tailscale/apitype from tailscale.com/cmd/tailscale/cli+ tailscale.com/cmd/tailscale/cli from tailscale.com/cmd/tailscale + tailscale.com/control/controlbase from tailscale.com/control/controlhttp + tailscale.com/control/controlhttp from tailscale.com/cmd/tailscale/cli tailscale.com/control/controlknobs from tailscale.com/net/portmapper tailscale.com/derp from tailscale.com/derp/derphttp tailscale.com/derp/derphttp from tailscale.com/net/netcheck @@ -48,18 +50,19 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep tailscale.com/ipn from tailscale.com/cmd/tailscale/cli+ tailscale.com/ipn/ipnstate from tailscale.com/cmd/tailscale/cli+ 💣 tailscale.com/metrics from tailscale.com/derp - tailscale.com/net/dnscache from tailscale.com/derp/derphttp + tailscale.com/net/dnscache from tailscale.com/derp/derphttp+ + tailscale.com/net/dnsfallback from tailscale.com/control/controlhttp tailscale.com/net/flowtrack from tailscale.com/wgengine/filter+ 💣 tailscale.com/net/interfaces from tailscale.com/cmd/tailscale/cli+ tailscale.com/net/netcheck from tailscale.com/cmd/tailscale/cli tailscale.com/net/neterror from tailscale.com/net/netcheck+ tailscale.com/net/netknob from tailscale.com/net/netns tailscale.com/net/netns from tailscale.com/derp/derphttp+ - tailscale.com/net/netutil from tailscale.com/client/tailscale + tailscale.com/net/netutil from tailscale.com/client/tailscale+ tailscale.com/net/packet from tailscale.com/wgengine/filter tailscale.com/net/portmapper from tailscale.com/net/netcheck+ tailscale.com/net/stun from tailscale.com/net/netcheck - tailscale.com/net/tlsdial from tailscale.com/derp/derphttp + tailscale.com/net/tlsdial from tailscale.com/derp/derphttp+ tailscale.com/net/tsaddr from tailscale.com/net/interfaces+ 💣 tailscale.com/net/tshttpproxy from tailscale.com/derp/derphttp+ tailscale.com/paths from tailscale.com/cmd/tailscale/cli+ @@ -92,12 +95,13 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep tailscale.com/version/distro from tailscale.com/cmd/tailscale/cli+ tailscale.com/wgengine/filter from tailscale.com/types/netmap golang.org/x/crypto/blake2b from golang.org/x/crypto/nacl/box + golang.org/x/crypto/blake2s from tailscale.com/control/controlbase golang.org/x/crypto/chacha20 from golang.org/x/crypto/chacha20poly1305 - golang.org/x/crypto/chacha20poly1305 from crypto/tls + golang.org/x/crypto/chacha20poly1305 from crypto/tls+ golang.org/x/crypto/cryptobyte from crypto/ecdsa+ golang.org/x/crypto/cryptobyte/asn1 from crypto/ecdsa+ golang.org/x/crypto/curve25519 from crypto/tls+ - golang.org/x/crypto/hkdf from crypto/tls + golang.org/x/crypto/hkdf from crypto/tls+ golang.org/x/crypto/nacl/box from tailscale.com/types/key golang.org/x/crypto/nacl/secretbox from golang.org/x/crypto/nacl/box golang.org/x/crypto/salsa20/salsa from golang.org/x/crypto/nacl/box+