mirror of
https://github.com/tailscale/tailscale.git
synced 2025-10-20 15:10:43 +00:00
wgengine/magicsock: update discokeys on netmap change.
Fixes #3008. Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
committed by
Dave Anderson
parent
2d11503cff
commit
830f641c6b
@@ -136,13 +136,17 @@ type magicStack struct {
|
||||
// friends. You need to call conn.SetNetworkMap and dev.Reconfig
|
||||
// before anything interesting happens.
|
||||
func newMagicStack(t testing.TB, logf logger.Logf, l nettype.PacketListener, derpMap *tailcfg.DERPMap) *magicStack {
|
||||
t.Helper()
|
||||
|
||||
privateKey, err := wgkey.NewPrivate()
|
||||
if err != nil {
|
||||
t.Fatalf("generating private key: %v", err)
|
||||
}
|
||||
|
||||
return newMagicStackWithKey(t, logf, l, derpMap, privateKey)
|
||||
}
|
||||
|
||||
func newMagicStackWithKey(t testing.TB, logf logger.Logf, l nettype.PacketListener, derpMap *tailcfg.DERPMap, privateKey wgkey.Private) *magicStack {
|
||||
t.Helper()
|
||||
|
||||
epCh := make(chan []tailcfg.Endpoint, 100) // arbitrary
|
||||
conn, err := NewConn(Options{
|
||||
Logf: logf,
|
||||
@@ -647,6 +651,76 @@ func TestNoDiscoKey(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscokeyChange(t *testing.T) {
|
||||
tstest.PanicOnLog()
|
||||
tstest.ResourceCheck(t)
|
||||
|
||||
derpMap, cleanup := runDERPAndStun(t, t.Logf, localhostListener{}, netaddr.IPv4(127, 0, 0, 1))
|
||||
defer cleanup()
|
||||
|
||||
m1Key, err := wgkey.NewPrivate()
|
||||
if err != nil {
|
||||
t.Fatalf("generating nodekey: %v", err)
|
||||
}
|
||||
m1 := newMagicStackWithKey(t, t.Logf, localhostListener{}, derpMap, m1Key)
|
||||
defer m1.Close()
|
||||
m2 := newMagicStack(t, t.Logf, localhostListener{}, derpMap)
|
||||
defer m2.Close()
|
||||
|
||||
var (
|
||||
mu sync.Mutex
|
||||
// Start with some random discoKey that isn't actually m1's key,
|
||||
// to simulate m2 coming up with knowledge of an old, expired
|
||||
// discokey. We'll switch to the correct one later in the test.
|
||||
m1DiscoKey = tailcfg.DiscoKey(key.NewPrivate().Public())
|
||||
)
|
||||
setm1Key := func(idx int, nm *netmap.NetworkMap) {
|
||||
if idx != 1 {
|
||||
// only mutate m2's netmap
|
||||
return
|
||||
}
|
||||
if len(nm.Peers) != 1 {
|
||||
// m1 not in netmap yet.
|
||||
return
|
||||
}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
nm.Peers[0].DiscoKey = m1DiscoKey
|
||||
}
|
||||
|
||||
cleanupMesh := meshStacks(t.Logf, setm1Key, m1, m2)
|
||||
defer cleanupMesh()
|
||||
|
||||
// Wait for both peers to know about each other.
|
||||
for {
|
||||
if s1 := m1.Status(); len(s1.Peer) != 1 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
if s2 := m2.Status(); len(s2.Peer) != 1 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
m1DiscoKey = m1.conn.DiscoPublicKey()
|
||||
mu.Unlock()
|
||||
|
||||
// Manually trigger an endpoint update to meshStacks, so it hands
|
||||
// m2 a new netmap.
|
||||
m1.conn.mu.Lock()
|
||||
m1.epCh <- m1.conn.lastEndpoints
|
||||
m1.conn.mu.Unlock()
|
||||
|
||||
cleanup = newPinger(t, t.Logf, m1, m2)
|
||||
defer cleanup()
|
||||
|
||||
mustDirect(t, t.Logf, m1, m2)
|
||||
mustDirect(t, t.Logf, m2, m1)
|
||||
}
|
||||
|
||||
func TestActiveDiscovery(t *testing.T) {
|
||||
t.Run("simple_internet", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
@@ -878,30 +952,29 @@ func testActiveDiscovery(t *testing.T, d *devices) {
|
||||
// Everything is now up and running, active discovery should find
|
||||
// a direct path between our peers. Wait for it to switch away
|
||||
// from DERP.
|
||||
|
||||
mustDirect := func(m1, m2 *magicStack) {
|
||||
lastLog := time.Now().Add(-time.Minute)
|
||||
// See https://github.com/tailscale/tailscale/issues/654 for a discussion of this deadline.
|
||||
for deadline := time.Now().Add(10 * time.Second); time.Now().Before(deadline); time.Sleep(10 * time.Millisecond) {
|
||||
pst := m1.Status().Peer[m2.Public()]
|
||||
if pst.CurAddr != "" {
|
||||
logf("direct link %s->%s found with addr %s", m1, m2, pst.CurAddr)
|
||||
return
|
||||
}
|
||||
if now := time.Now(); now.Sub(lastLog) > time.Second {
|
||||
logf("no direct path %s->%s yet, addrs %v", m1, m2, pst.Addrs)
|
||||
lastLog = now
|
||||
}
|
||||
}
|
||||
t.Errorf("magicsock did not find a direct path from %s to %s", m1, m2)
|
||||
}
|
||||
|
||||
mustDirect(m1, m2)
|
||||
mustDirect(m2, m1)
|
||||
mustDirect(t, logf, m1, m2)
|
||||
mustDirect(t, logf, m2, m1)
|
||||
|
||||
logf("starting cleanup")
|
||||
}
|
||||
|
||||
func mustDirect(t *testing.T, logf logger.Logf, m1, m2 *magicStack) {
|
||||
lastLog := time.Now().Add(-time.Minute)
|
||||
// See https://github.com/tailscale/tailscale/issues/654 for a discussion of this deadline.
|
||||
for deadline := time.Now().Add(10 * time.Second); time.Now().Before(deadline); time.Sleep(10 * time.Millisecond) {
|
||||
pst := m1.Status().Peer[m2.Public()]
|
||||
if pst.CurAddr != "" {
|
||||
logf("direct link %s->%s found with addr %s", m1, m2, pst.CurAddr)
|
||||
return
|
||||
}
|
||||
if now := time.Now(); now.Sub(lastLog) > time.Second {
|
||||
logf("no direct path %s->%s yet, addrs %v", m1, m2, pst.Addrs)
|
||||
lastLog = now
|
||||
}
|
||||
}
|
||||
t.Errorf("magicsock did not find a direct path from %s to %s", m1, m2)
|
||||
}
|
||||
|
||||
func testTwoDevicePing(t *testing.T, d *devices) {
|
||||
tstest.PanicOnLog()
|
||||
tstest.ResourceCheck(t)
|
||||
|
||||
Reference in New Issue
Block a user