wgengine/magicsock: prune key.Public-keyed on peer removals

Fixes #215
pull/308/head
Brad Fitzpatrick 2020-04-18 08:48:01 -07:00
parent 00d053e25a
commit 268d331cb5
2 changed files with 31 additions and 4 deletions

View File

@ -81,6 +81,7 @@ type Conn struct {
endpointsUpdateActive bool endpointsUpdateActive bool
wantEndpointsUpdate string // non-empty for why reason wantEndpointsUpdate string // non-empty for why reason
lastEndpoints []string lastEndpoints []string
peerSet map[key.Public]struct{}
// addrsByUDP is a map of every remote ip:port to a priority // addrsByUDP is a map of every remote ip:port to a priority
// list of endpoint addresses for a peer. // list of endpoint addresses for a peer.
@ -95,9 +96,9 @@ type Conn struct {
// 10.0.0.3:3 -> [10.0.0.3:3] // 10.0.0.3:3 -> [10.0.0.3:3]
addrsByUDP map[netaddr.IPPort]*AddrSet addrsByUDP map[netaddr.IPPort]*AddrSet
// addsByKey maps from public keys (as seen by incoming DERP // addrsByKey maps from public keys (as seen by incoming DERP
// packets) to its AddrSet (the same values as in addrsByUDP). // packets) to its AddrSet (the same values as in addrsByUDP).
addrsByKey map[key.Public]*AddrSet // TODO(#215): remove entries when peers go away addrsByKey map[key.Public]*AddrSet
netInfoFunc func(*tailcfg.NetInfo) // nil until set netInfoFunc func(*tailcfg.NetInfo) // nil until set
netInfoLast *tailcfg.NetInfo netInfoLast *tailcfg.NetInfo
@ -116,11 +117,11 @@ type Conn struct {
// home connection, or what was once our home), then we // home connection, or what was once our home), then we
// remember that route here to optimistically use instead of // remember that route here to optimistically use instead of
// creating a new DERP connection back to their home. // creating a new DERP connection back to their home.
derpRoute map[key.Public]derpRoute // TODO(#215): remove entries when peers go away derpRoute map[key.Public]derpRoute
// peerLastDerp tracks which DERP node we last used to speak with a // peerLastDerp tracks which DERP node we last used to speak with a
// peer. It's only used to quiet logging, so we only log on change. // peer. It's only used to quiet logging, so we only log on change.
peerLastDerp map[key.Public]int // TODO(#215): remove entries when peers go away peerLastDerp map[key.Public]int
} }
// derpRoute is a route entry for a public key, saying that a certain // derpRoute is a route entry for a public key, saying that a certain
@ -1240,6 +1241,28 @@ func (c *Conn) SetPrivateKey(privateKey wgcfg.PrivateKey) error {
return nil return nil
} }
// UpdatePeers is called when the set of WireGuard peers changes. It
// then removes any state for old peers.
//
// The caller passes ownership of newPeers map to UpdatePeers.
func (c *Conn) UpdatePeers(newPeers map[key.Public]struct{}) {
c.mu.Lock()
defer c.mu.Unlock()
oldPeers := c.peerSet
c.peerSet = newPeers
// Clean up any key.Public-keyed maps for peers that no longer
// exist.
for peer := range oldPeers {
if _, ok := newPeers[peer]; !ok {
delete(c.addrsByKey, peer)
delete(c.derpRoute, peer)
delete(c.peerLastDerp, peer)
}
}
}
// SetDERPEnabled controls whether DERP is used. // SetDERPEnabled controls whether DERP is used.
// New connections have it enabled by default. // New connections have it enabled by default.
func (c *Conn) SetDERPEnabled(wantDerp bool) { func (c *Conn) SetDERPEnabled(wantDerp bool) {

View File

@ -327,10 +327,12 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, dnsDomains []string) error
e.wgLock.Lock() e.wgLock.Lock()
defer e.wgLock.Unlock() defer e.wgLock.Unlock()
peerSet := make(map[key.Public]struct{}, len(cfg.Peers))
e.mu.Lock() e.mu.Lock()
e.peerSequence = e.peerSequence[:0] e.peerSequence = e.peerSequence[:0]
for _, p := range cfg.Peers { for _, p := range cfg.Peers {
e.peerSequence = append(e.peerSequence, p.PublicKey) e.peerSequence = append(e.peerSequence, p.PublicKey)
peerSet[key.Public(p.PublicKey)] = struct{}{}
} }
e.mu.Unlock() e.mu.Unlock()
@ -362,6 +364,8 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, dnsDomains []string) error
return err return err
} }
e.magicConn.UpdatePeers(peerSet)
// TODO(apenwarr): only handling the first local address. // TODO(apenwarr): only handling the first local address.
// Currently we never use more than one anyway. // Currently we never use more than one anyway.
var cidr wgcfg.CIDR var cidr wgcfg.CIDR