diff --git a/cmd/tailscale/cli/exitnode.go b/cmd/tailscale/cli/exitnode.go index 77e2453d0..549ecfc33 100644 --- a/cmd/tailscale/cli/exitnode.go +++ b/cmd/tailscale/cli/exitnode.go @@ -37,6 +37,16 @@ return fs })(), }, + { + Name: "suggest", + ShortUsage: "exit-node suggest", + ShortHelp: "Picks the best available exit node", + Exec: runExitNodeSuggest, + FlagSet: (func() *flag.FlagSet { + fs := newFlagSet("suggest") + return fs + })(), + }, }, Exec: func(context.Context, []string) error { return errors.New("exit-node subcommand required; run 'tailscale exit-node -h' for details") @@ -102,6 +112,14 @@ func runExitNodeList(ctx context.Context, args []string) error { return nil } +func runExitNodeSuggest(ctx context.Context, args []string) error { + err := localClient.SuggestExitNode(ctx) + if err != nil { + return fmt.Errorf("Failed to suggest exit node. Error: %v", err) + } + return nil +} + // peerStatus returns a string representing the current state of // a peer. If there is no notable state, a - is returned. func peerStatus(peer *ipnstate.PeerStatus) string { diff --git a/cmd/tailscale/cli/set.go b/cmd/tailscale/cli/set.go index a5623cc33..31c249952 100644 --- a/cmd/tailscale/cli/set.go +++ b/cmd/tailscale/cli/set.go @@ -64,7 +64,7 @@ func newSetFlagSet(goos string, setArgs *setArgsT) *flag.FlagSet { setf.StringVar(&setArgs.profileName, "nickname", "", "nickname for the current account") setf.BoolVar(&setArgs.acceptRoutes, "accept-routes", false, "accept routes advertised by other Tailscale nodes") setf.BoolVar(&setArgs.acceptDNS, "accept-dns", false, "accept DNS configuration from the admin panel") - setf.StringVar(&setArgs.exitNodeIP, "exit-node", "", "Tailscale exit node (IP or base name) for internet traffic, or empty string to not use an exit node. Input suggest as the string for Tailscale to pick the best exit node.") + setf.StringVar(&setArgs.exitNodeIP, "exit-node", "", "Tailscale exit node (IP or base name) for internet traffic, or empty string to not use an exit node.") setf.BoolVar(&setArgs.exitNodeAllowLANAccess, "exit-node-allow-lan-access", false, "Allow direct access to the local network when routing traffic via an exit node") setf.BoolVar(&setArgs.shieldsUp, "shields-up", false, "don't allow incoming connections") setf.BoolVar(&setArgs.runSSH, "ssh", false, "run an SSH server, permitting access per tailnet admin's declared policy") @@ -128,19 +128,12 @@ func runSet(ctx context.Context, args []string) (retErr error) { } if setArgs.exitNodeIP != "" { - if setArgs.exitNodeIP == "suggest" { - err := localClient.SuggestExitNode(ctx) - if err != nil { - return err - } - } else { - if err := maskedPrefs.Prefs.SetExitNodeIP(setArgs.exitNodeIP, st); err != nil { - var e ipn.ExitNodeLocalIPError - if errors.As(err, &e) { - return fmt.Errorf("%w; did you mean --advertise-exit-node?", err) - } - return err + if err := maskedPrefs.Prefs.SetExitNodeIP(setArgs.exitNodeIP, st); err != nil { + var e ipn.ExitNodeLocalIPError + if errors.As(err, &e) { + return fmt.Errorf("%w; did you mean --advertise-exit-node?", err) } + return err } }