|
|
|
|
@ -18,6 +18,7 @@ import ( |
|
|
|
|
"net" |
|
|
|
|
"net/http" |
|
|
|
|
"net/netip" |
|
|
|
|
"net/url" |
|
|
|
|
"os" |
|
|
|
|
"runtime" |
|
|
|
|
"strconv" |
|
|
|
|
@ -25,14 +26,17 @@ import ( |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"github.com/peterbourgon/ff/v3/ffcli" |
|
|
|
|
"golang.org/x/net/http/httpproxy" |
|
|
|
|
"tailscale.com/control/controlhttp" |
|
|
|
|
"tailscale.com/hostinfo" |
|
|
|
|
"tailscale.com/ipn" |
|
|
|
|
"tailscale.com/net/tsaddr" |
|
|
|
|
"tailscale.com/net/tshttpproxy" |
|
|
|
|
"tailscale.com/paths" |
|
|
|
|
"tailscale.com/safesocket" |
|
|
|
|
"tailscale.com/tailcfg" |
|
|
|
|
"tailscale.com/types/key" |
|
|
|
|
"tailscale.com/types/logger" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
var debugCmd = &ffcli.Command{ |
|
|
|
|
@ -141,6 +145,7 @@ var debugCmd = &ffcli.Command{ |
|
|
|
|
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") |
|
|
|
|
fs.BoolVar(&ts2021Args.verbose, "verbose", false, "be extra verbose") |
|
|
|
|
return fs |
|
|
|
|
})(), |
|
|
|
|
}, |
|
|
|
|
@ -465,19 +470,35 @@ func runVia(ctx context.Context, args []string) error { |
|
|
|
|
var ts2021Args struct { |
|
|
|
|
host string // "controlplane.tailscale.com"
|
|
|
|
|
version int // 27 or whatever
|
|
|
|
|
verbose bool |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func runTS2021(ctx context.Context, args []string) error { |
|
|
|
|
log.SetOutput(os.Stdout) |
|
|
|
|
log.SetFlags(log.Ltime | log.Lmicroseconds) |
|
|
|
|
|
|
|
|
|
keysURL := "https://" + ts2021Args.host + "/key?v=" + strconv.Itoa(ts2021Args.version) |
|
|
|
|
|
|
|
|
|
if ts2021Args.verbose { |
|
|
|
|
u, err := url.Parse(keysURL) |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
envConf := httpproxy.FromEnvironment() |
|
|
|
|
if *envConf == (httpproxy.Config{}) { |
|
|
|
|
log.Printf("HTTP proxy env: (none)") |
|
|
|
|
} else { |
|
|
|
|
log.Printf("HTTP proxy env: %+v", envConf) |
|
|
|
|
} |
|
|
|
|
proxy, err := tshttpproxy.ProxyFromEnvironment(&http.Request{URL: u}) |
|
|
|
|
log.Printf("tshttpproxy.ProxyFromEnvironment = (%v, %v)", proxy, err) |
|
|
|
|
} |
|
|
|
|
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 { |
|
|
|
|
@ -497,6 +518,9 @@ func runTS2021(ctx context.Context, args []string) error { |
|
|
|
|
return fmt.Errorf("decoding /keys JSON: %w", err) |
|
|
|
|
} |
|
|
|
|
res.Body.Close() |
|
|
|
|
if ts2021Args.verbose { |
|
|
|
|
log.Printf("got public key: %v", keys.PublicKey) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dialFunc := func(ctx context.Context, network, address string) (net.Conn, error) { |
|
|
|
|
log.Printf("Dial(%q, %q) ...", network, address) |
|
|
|
|
@ -508,7 +532,10 @@ func runTS2021(ctx context.Context, args []string) error { |
|
|
|
|
} |
|
|
|
|
return c, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var logf logger.Logf |
|
|
|
|
if ts2021Args.verbose { |
|
|
|
|
logf = log.Printf |
|
|
|
|
} |
|
|
|
|
conn, err := (&controlhttp.Dialer{ |
|
|
|
|
Hostname: ts2021Args.host, |
|
|
|
|
HTTPPort: "80", |
|
|
|
|
@ -517,6 +544,7 @@ func runTS2021(ctx context.Context, args []string) error { |
|
|
|
|
ControlKey: keys.PublicKey, |
|
|
|
|
ProtocolVersion: uint16(ts2021Args.version), |
|
|
|
|
Dialer: dialFunc, |
|
|
|
|
Logf: logf, |
|
|
|
|
}).Dial(ctx) |
|
|
|
|
log.Printf("controlhttp.Dial = %p, %v", conn, err) |
|
|
|
|
if err != nil { |
|
|
|
|
|