From f27a57911b5bc405a44584d7fcf7907c70ae7805 Mon Sep 17 00:00:00 2001 From: halulu Date: Wed, 26 Aug 2020 07:26:10 +0800 Subject: [PATCH] cmd/tailscale: add derp and endpoints status (#703) cmd/tailscale: add local node's information to status output (by default) RELNOTE=yes Updates #477 Signed-off-by: Halulu --- cmd/tailscale/cli/status.go | 22 ++++++++++++++++------ ipn/ipnstate/ipnstate.go | 13 +++++++++++-- wgengine/magicsock/magicsock.go | 17 +++++++++++++++++ 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/cmd/tailscale/cli/status.go b/cmd/tailscale/cli/status.go index 4fa899626..806f439f2 100644 --- a/cmd/tailscale/cli/status.go +++ b/cmd/tailscale/cli/status.go @@ -33,6 +33,7 @@ var statusCmd = &ffcli.Command{ fs.BoolVar(&statusArgs.json, "json", false, "output in JSON format (WARNING: format subject to change)") fs.BoolVar(&statusArgs.web, "web", false, "run webserver with HTML showing status") fs.BoolVar(&statusArgs.active, "active", false, "filter output to only peers with active sessions (not applicable to web mode)") + fs.BoolVar(&statusArgs.self, "self", true, "show status of local machine") fs.StringVar(&statusArgs.listen, "listen", "127.0.0.1:8384", "listen address; use port 0 for automatic") fs.BoolVar(&statusArgs.browser, "browser", true, "Open a browser in web mode") return fs @@ -45,6 +46,7 @@ var statusArgs struct { listen string // in web mode, webserver address to listen on, empty means auto browser bool // in web mode, whether to open browser active bool // in CLI mode, filter output to only peers with active sessions + self bool // in CLI mode, show status of local machine } func runStatus(ctx context.Context, args []string) error { @@ -127,14 +129,10 @@ func runStatus(ctx context.Context, args []string) error { var buf bytes.Buffer f := func(format string, a ...interface{}) { fmt.Fprintf(&buf, format, a...) } - for _, peer := range st.Peers() { - ps := st.Peer[peer] + printPS := func(ps *ipnstate.PeerStatus) { active := peerActive(ps) - if statusArgs.active && !active { - continue - } f("%s %-7s %-15s %-18s tx=%8d rx=%8d ", - peer.ShortString(), + ps.PublicKey.ShortString(), ps.OS, ps.TailAddr, ps.SimpleHostName(), @@ -160,6 +158,18 @@ func runStatus(ctx context.Context, args []string) error { } f("\n") } + + if statusArgs.self && st.Self != nil { + printPS(st.Self) + } + for _, peer := range st.Peers() { + ps := st.Peer[peer] + active := peerActive(ps) + if statusArgs.active && !active { + continue + } + printPS(ps) + } os.Stdout.Write(buf.Bytes()) return nil } diff --git a/ipn/ipnstate/ipnstate.go b/ipn/ipnstate/ipnstate.go index e33cbbef8..67a115ee2 100644 --- a/ipn/ipnstate/ipnstate.go +++ b/ipn/ipnstate/ipnstate.go @@ -27,8 +27,10 @@ import ( type Status struct { BackendState string TailscaleIPs []netaddr.IP // Tailscale IP(s) assigned to this node - Peer map[key.Public]*PeerStatus - User map[tailcfg.UserID]tailcfg.UserProfile + Self *PeerStatus + + Peer map[key.Public]*PeerStatus + User map[tailcfg.UserID]tailcfg.UserProfile } func (s *Status) Peers() []key.Public { @@ -95,6 +97,13 @@ func (sb *StatusBuilder) Status() *Status { return &sb.st } +// SetSelfStatus sets the status of the local machine. +func (sb *StatusBuilder) SetSelfStatus(ss *PeerStatus) { + sb.mu.Lock() + defer sb.mu.Unlock() + sb.st.Self = ss +} + // AddUser adds a user profile to the status. func (sb *StatusBuilder) AddUser(id tailcfg.UserID, up tailcfg.UserProfile) { sb.mu.Lock() diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index d12f2cf08..8e27b3ed3 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -3034,6 +3034,21 @@ func (c *Conn) UpdateStatus(sb *ipnstate.StatusBuilder) { c.mu.Lock() defer c.mu.Unlock() + ss := &ipnstate.PeerStatus{ + PublicKey: c.privateKey.Public(), + Addrs: c.lastEndpoints, + } + if c.netMap != nil { + ss.HostName = c.netMap.Hostinfo.Hostname + ss.OS = c.netMap.Hostinfo.OS + } + if c.derpMap != nil { + derpRegion, ok := c.derpMap.Regions[c.myDerp] + if ok { + ss.Relay = derpRegion.RegionCode + } + } + if c.netMap != nil { for _, addr := range c.netMap.Addresses { if (addr.IP.Is4() && addr.Mask != 32) || (addr.IP.Is6() && addr.Mask != 128) { @@ -3041,9 +3056,11 @@ func (c *Conn) UpdateStatus(sb *ipnstate.StatusBuilder) { } if ip, ok := netaddr.FromStdIP(addr.IP.IP()); ok { sb.AddTailscaleIP(ip) + ss.TailAddr = ip.String() } } } + sb.SetSelfStatus(ss) for dk, n := range c.nodeOfDisco { ps := &ipnstate.PeerStatus{InMagicSock: true}