derp: add frameClosePeer to move around clients within a region
For various reasons (mostly during rollouts or config changes on our side), nodes may end up connecting to a fallback DERP node in a region, rather than the primary one we tell them about in the DERP map. Connecting to the "wrong" node is fine, but it's in our best interest for all nodes in a domain to connect to the same node, to reduce intra-region packet forwarding. This adds a privileged frame type used by the control system that can kick off a client connection when they're connected to the wrong node in a region. Then they hopefully reconnect immediately to the correct location. (If not, we can leave them alone and stop closing them.) Updates tailscale/corp#372
This commit is contained in:
@ -420,6 +420,8 @@ func (c *sclient) run(ctx context.Context) error {
|
||||
err = c.handleFrameForwardPacket(ft, fl)
|
||||
case frameWatchConns:
|
||||
err = c.handleFrameWatchConns(ft, fl)
|
||||
case frameClosePeer:
|
||||
err = c.handleFrameClosePeer(ft, fl)
|
||||
default:
|
||||
err = c.handleUnknownFrame(ft, fl)
|
||||
}
|
||||
@ -457,6 +459,32 @@ func (c *sclient) handleFrameWatchConns(ft frameType, fl uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *sclient) handleFrameClosePeer(ft frameType, fl uint32) error {
|
||||
if fl != keyLen {
|
||||
return fmt.Errorf("handleFrameClosePeer wrong size")
|
||||
}
|
||||
if !c.canMesh {
|
||||
return fmt.Errorf("insufficient permissions")
|
||||
}
|
||||
var targetKey key.Public
|
||||
if _, err := io.ReadFull(c.br, targetKey[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
s := c.s
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if target, ok := s.clients[targetKey]; ok {
|
||||
c.logf("frameClosePeer closing peer %x", targetKey)
|
||||
go target.nc.Close()
|
||||
} else {
|
||||
c.logf("frameClosePeer failed to find peer %x", targetKey)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// handleFrameForwardPacket reads a "forward packet" frame from the client
|
||||
// (which must be a trusted client, a peer in our mesh).
|
||||
func (c *sclient) handleFrameForwardPacket(ft frameType, fl uint32) error {
|
||||
|
Reference in New Issue
Block a user