diff --git a/derp/derp_server.go b/derp/derp_server.go index f86ac862d..451e49939 100644 --- a/derp/derp_server.go +++ b/derp/derp_server.go @@ -1006,10 +1006,10 @@ func (s *Server) verifyClient(clientKey key.NodePublic, info *clientInfo) error if err != nil { return fmt.Errorf("failed to query local tailscaled status: %w", err) } - if clientKey == key.NodePublicFromRaw32(mem.B(status.Self.PublicKey[:])) { + if clientKey == status.Self.PublicKey { return nil } - if _, exists := status.Peer[clientKey.AsPublic()]; !exists { + if _, exists := status.Peer[clientKey]; !exists { return fmt.Errorf("client %v not in set of peers", clientKey) } // TODO(bradfitz): add policy for configurable bandwidth rate per client? diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index ebe8d7557..b0a1a0f09 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -26,6 +26,7 @@ import ( "time" "github.com/go-multierror/multierror" + "go4.org/mem" "inet.af/netaddr" "tailscale.com/client/tailscale/apitype" "tailscale.com/control/controlclient" @@ -388,7 +389,7 @@ func (b *LocalBackend) populatePeerStatusLocked(sb *ipnstate.StatusBuilder) { tailscaleIPs = append(tailscaleIPs, addr.IP()) } } - sb.AddPeer(key.Public(p.Key), &ipnstate.PeerStatus{ + sb.AddPeer(key.NodePublicFromRaw32(mem.B(p.Key[:])), &ipnstate.PeerStatus{ InNetworkMap: true, ID: p.StableID, UserID: p.User, diff --git a/ipn/ipnstate/ipnstate.go b/ipn/ipnstate/ipnstate.go index 196659a3d..73c7467b6 100644 --- a/ipn/ipnstate/ipnstate.go +++ b/ipn/ipnstate/ipnstate.go @@ -8,7 +8,6 @@ package ipnstate import ( - "bytes" "fmt" "html" "io" @@ -57,16 +56,16 @@ type Status struct { // trailing periods, and without any "_acme-challenge." prefix. CertDomains []string - Peer map[key.Public]*PeerStatus + Peer map[key.NodePublic]*PeerStatus User map[tailcfg.UserID]tailcfg.UserProfile } -func (s *Status) Peers() []key.Public { - kk := make([]key.Public, 0, len(s.Peer)) +func (s *Status) Peers() []key.NodePublic { + kk := make([]key.NodePublic, 0, len(s.Peer)) for k := range s.Peer { kk = append(kk, k) } - sort.Slice(kk, func(i, j int) bool { return bytes.Compare(kk[i][:], kk[j][:]) < 0 }) + sort.Slice(kk, func(i, j int) bool { return kk[i].Less(kk[j]) }) return kk } @@ -78,7 +77,7 @@ type PeerStatusLite struct { type PeerStatus struct { ID tailcfg.StableNodeID - PublicKey key.Public + PublicKey key.NodePublic HostName string // HostInfo's Hostname (not a DNS name or necessarily unique) DNSName string OS string // HostInfo.OS @@ -201,7 +200,7 @@ func (sb *StatusBuilder) AddTailscaleIP(ip netaddr.IP) { // AddPeer adds a peer node to the status. // // Its PeerStatus is mixed with any previous status already added. -func (sb *StatusBuilder) AddPeer(peer key.Public, st *PeerStatus) { +func (sb *StatusBuilder) AddPeer(peer key.NodePublic, st *PeerStatus) { if st == nil { panic("nil PeerStatus") } @@ -214,7 +213,7 @@ func (sb *StatusBuilder) AddPeer(peer key.Public, st *PeerStatus) { } if sb.st.Peer == nil { - sb.st.Peer = make(map[key.Public]*PeerStatus) + sb.st.Peer = make(map[key.NodePublic]*PeerStatus) } e, ok := sb.st.Peer[peer] if !ok { @@ -478,5 +477,6 @@ func sortKey(ps *PeerStatus) string { if len(ps.TailscaleIPs) > 0 { return ps.TailscaleIPs[0].String() } - return string(ps.PublicKey[:]) + raw := ps.PublicKey.Raw32() + return string(raw[:]) } diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 0b9241cc9..bdb47e953 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -3081,7 +3081,11 @@ func (c *Conn) UpdateStatus(sb *ipnstate.StatusBuilder) { } sb.MutateSelfStatus(func(ss *ipnstate.PeerStatus) { - ss.PublicKey = c.privateKey.Public() + if !c.privateKey.IsZero() { + ss.PublicKey = key.NodePrivateFromRaw32(mem.B(c.privateKey[:])).Public() + } else { + ss.PublicKey = key.NodePublic{} + } ss.Addrs = make([]string, 0, len(c.lastEndpoints)) for _, ep := range c.lastEndpoints { ss.Addrs = append(ss.Addrs, ep.Addr.String()) @@ -3113,7 +3117,7 @@ func (c *Conn) UpdateStatus(sb *ipnstate.StatusBuilder) { ps := &ipnstate.PeerStatus{InMagicSock: true} //ps.Addrs = append(ps.Addrs, n.Endpoints...) ep.populatePeerStatus(ps) - sb.AddPeer(key.Public(ep.publicKey), ps) + sb.AddPeer(key.NodePublicFromRaw32(mem.B(ep.publicKey[:])), ps) }) c.foreachActiveDerpSortedLocked(func(node int, ad activeDerp) { diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index d51fb66e1..fb008dbb0 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -205,8 +205,8 @@ func (s *magicStack) Close() { s.conn.Close() } -func (s *magicStack) Public() key.Public { - return s.privateKey.Public().AsPublic() +func (s *magicStack) Public() key.NodePublic { + return s.privateKey.Public() } func (s *magicStack) Status() *ipnstate.Status { @@ -995,10 +995,10 @@ func testTwoDevicePing(t *testing.T, d *devices) { // Wait for magicsock to be told about peers from meshStacks. tstest.WaitFor(10*time.Second, func() error { - if p := m1.Status().Peer[m2.privateKey.Public().AsPublic()]; p == nil || !p.InMagicSock { + if p := m1.Status().Peer[m2.Public()]; p == nil || !p.InMagicSock { return errors.New("m1 not ready") } - if p := m2.Status().Peer[m1.privateKey.Public().AsPublic()]; p == nil || !p.InMagicSock { + if p := m2.Status().Peer[m1.Public()]; p == nil || !p.InMagicSock { return errors.New("m2 not ready") } return nil diff --git a/wgengine/userspace.go b/wgengine/userspace.go index 0add62f99..934b2f990 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -1242,7 +1242,7 @@ func (e *userspaceEngine) UpdateStatus(sb *ipnstate.StatusBuilder) { return } for _, ps := range st.Peers { - sb.AddPeer(key.Public(ps.NodeKey), &ipnstate.PeerStatus{ + sb.AddPeer(key.NodePublicFromRaw32(mem.B(ps.NodeKey[:])), &ipnstate.PeerStatus{ RxBytes: int64(ps.RxBytes), TxBytes: int64(ps.TxBytes), LastHandshake: ps.LastHandshake,