Skip to content

Commit 5beb71a

Browse files
committed
Wipe all endpoints on BlockEndpoints
1 parent b22cdd1 commit 5beb71a

File tree

3 files changed

+31
-35
lines changed

3 files changed

+31
-35
lines changed

wgengine/magicsock/endpoint.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,19 @@ func (de *endpoint) deleteEndpointLocked(why string, ep netip.AddrPort) {
207207
}
208208
}
209209

210+
func (de *endpoint) clearEndpoints(why string) {
211+
de.mu.Lock()
212+
defer de.mu.Unlock()
213+
de.debugUpdates.Add(EndpointChange{
214+
When: time.Now(),
215+
What: "clearEndpoints-" + why,
216+
})
217+
de.endpointState = map[netip.AddrPort]*endpointState{}
218+
de.bestAddr = addrLatency{}
219+
de.c.logf("magicsock: disco: node %s %s now using DERP only (all endpoints deleted)",
220+
de.publicKey.ShortString(), de.discoShort())
221+
}
222+
210223
// initFakeUDPAddr populates fakeWGAddr with a globally unique fake UDPAddr.
211224
// The current implementation just uses the pointer value of de jammed into an IPv6
212225
// address, but it could also be, say, a counter.

wgengine/magicsock/magicsock.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,7 @@ type Conn struct {
218218
// endpoints gathered from local interfaces or STUN. Only DERP endpoints
219219
// will be sent.
220220
// This will also block incoming endpoints received via call-me-maybe disco
221-
// packets. Endpoints manually added (e.g. via coordination) will not be
222-
// blocked.
221+
// packets.
223222
blockEndpoints bool
224223
// endpointsUpdateActive indicates that updateEndpoints is
225224
// currently running. It's used to deduplicate concurrent endpoint
@@ -846,10 +845,10 @@ func (c *Conn) DiscoPublicKey() key.DiscoPublic {
846845
return c.discoPublic
847846
}
848847

849-
// SetBlockEndpoints sets the blockEndpoints field. If changed, endpoints will
850-
// be updated to apply the new settings. Existing connections may continue to
851-
// use the old setting until they are reestablished. Disabling endpoints does
852-
// not affect the UDP socket or portmapper.
848+
// SetBlockEndpoints sets the blockEndpoints field. If enabled, all peer
849+
// endpoints will be cleared from the peer map and every connection will
850+
// immediately switch to DERP. Disabling endpoints does not affect the UDP
851+
// socket or portmapper.
853852
func (c *Conn) SetBlockEndpoints(block bool) {
854853
c.mu.Lock()
855854
defer c.mu.Unlock()
@@ -874,11 +873,7 @@ func (c *Conn) SetBlockEndpoints(block bool) {
874873
// Clear any endpoints from the peerMap if block is true.
875874
if block {
876875
c.peerMap.forEachEndpoint(func(ep *endpoint) {
877-
// Simulate receiving a call-me-maybe disco packet with no
878-
// endpoints, which will cause all endpoints to be removed.
879-
ep.handleCallMeMaybe(&disco.CallMeMaybe{
880-
MyNumber: []netip.AddrPort{},
881-
})
876+
ep.clearEndpoints("SetBlockEndpoints")
882877
})
883878
}
884879
}
@@ -1944,6 +1939,13 @@ func (c *Conn) SetNetworkMap(nm *netmap.NetworkMap) {
19441939
// we'll fall through to the next pass, which allocates but can
19451940
// handle full set updates.
19461941
for _, n := range nm.Peers {
1942+
if c.blockEndpoints {
1943+
c.dlogf("[v1] magicsock: SetNetworkingMap: %v (%v, %v) received %d endpoints, but endpoints blocked",
1944+
n.DiscoKey.ShortString(), n.Key.ShortString(),
1945+
len(n.Endpoints),
1946+
)
1947+
n.Endpoints = []string{}
1948+
}
19471949
if ep, ok := c.peerMap.endpointForNodeKey(n.Key); ok {
19481950
if n.DiscoKey.IsZero() && !n.IsWireGuardOnly {
19491951
// Discokey transitioned from non-zero to zero? This should not

wgengine/magicsock/magicsock_test.go

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3097,35 +3097,16 @@ func TestBlockEndpointsDERPOK(t *testing.T) {
30973097
waitForEndpoints(t, ms1.conn)
30983098
waitForEndpoints(t, ms2.conn)
30993099

3100-
// meshStacks doesn't use call-me-maybe packets to update endpoints, which
3101-
// makes them not get cleared when we call SetBlockEndpoints.
3102-
ep2, ok := ms1.conn.peerMap.endpointForNodeKey(ms2.Public())
3103-
if !ok {
3104-
t.Fatalf("endpoint not found for ms2")
3105-
}
3106-
ep2.mu.Lock()
3107-
for k := range ep2.endpointState {
3108-
ep2.deleteEndpointLocked("TestBlockEndpointsDERPOK", k)
3109-
}
3110-
ep2.mu.Unlock()
3111-
3112-
// Wait for the call-me-maybe packet to arrive.
3113-
for i := 0; i < 50; i++ {
3114-
time.Sleep(100 * time.Millisecond)
3115-
ep2.mu.Lock()
3116-
if len(ep2.endpointState) != 0 {
3117-
ep2.mu.Unlock()
3118-
break
3119-
}
3120-
ep2.mu.Unlock()
3121-
}
3122-
31233100
// SetBlockEndpoints is called later since it's incompatible with the test
31243101
// meshStacks implementations.
31253102
// We only set it on ms1, since ms2's endpoints should be ignored by ms1.
31263103
ms1.conn.SetBlockEndpoints(true)
31273104

3128-
// All call-me-maybe endpoints should've been immediately removed from ms1.
3105+
// All endpoints should've been immediately removed from ms1.
3106+
ep2, ok := ms1.conn.peerMap.endpointForNodeKey(ms2.Public())
3107+
if !ok {
3108+
t.Fatalf("endpoint not found for ms2")
3109+
}
31293110
ep2.mu.Lock()
31303111
if len(ep2.endpointState) != 0 {
31313112
ep2.mu.Unlock()

0 commit comments

Comments
 (0)