derp, derphttp, magicsock: send new unknown peer frame when destination is unknown (#7552)
* wgengine/magicsock: add envknob to send CallMeMaybe to non-existent peer For testing older client version responses to the PeerGone packet format change. Updates #4326 Signed-off-by: Val <valerie@tailscale.com> * derp: remove dead sclient struct member replaceLimiter Leftover from an previous solution to the duplicate client problem. Updates #2751 Signed-off-by: Val <valerie@tailscale.com> * derp, derp/derphttp, wgengine/magicsock: add new PeerGone message type Not Here Extend the PeerGone message type by adding a reason byte. Send a PeerGone "Not Here" message when an endpoint sends a disco message to a peer that this server has no record of. Fixes #4326 Signed-off-by: Val <valerie@tailscale.com> --------- Signed-off-by: Val <valerie@tailscale.com>
This commit is contained in:
@ -25,6 +25,7 @@ import (
|
||||
|
||||
"go4.org/mem"
|
||||
"golang.org/x/time/rate"
|
||||
"tailscale.com/disco"
|
||||
"tailscale.com/net/memnet"
|
||||
"tailscale.com/types/key"
|
||||
"tailscale.com/types/logger"
|
||||
@ -105,7 +106,8 @@ func TestSendRecv(t *testing.T) {
|
||||
t.Logf("Connected client %d.", i)
|
||||
}
|
||||
|
||||
var peerGoneCount expvar.Int
|
||||
var peerGoneCountDisconnected expvar.Int
|
||||
var peerGoneCountNotHere expvar.Int
|
||||
|
||||
t.Logf("Starting read loops")
|
||||
for i := 0; i < numClients; i++ {
|
||||
@ -121,7 +123,14 @@ func TestSendRecv(t *testing.T) {
|
||||
t.Errorf("unexpected message type %T", m)
|
||||
continue
|
||||
case PeerGoneMessage:
|
||||
peerGoneCount.Add(1)
|
||||
switch m.Reason {
|
||||
case PeerGoneReasonDisconnected:
|
||||
peerGoneCountDisconnected.Add(1)
|
||||
case PeerGoneReasonNotHere:
|
||||
peerGoneCountNotHere.Add(1)
|
||||
default:
|
||||
t.Errorf("unexpected PeerGone reason %v", m.Reason)
|
||||
}
|
||||
case ReceivedPacket:
|
||||
if m.Source.IsZero() {
|
||||
t.Errorf("zero Source address in ReceivedPacket")
|
||||
@ -171,7 +180,19 @@ func TestSendRecv(t *testing.T) {
|
||||
var got int64
|
||||
dl := time.Now().Add(5 * time.Second)
|
||||
for time.Now().Before(dl) {
|
||||
if got = peerGoneCount.Value(); got == want {
|
||||
if got = peerGoneCountDisconnected.Value(); got == want {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Errorf("peer gone count = %v; want %v", got, want)
|
||||
}
|
||||
|
||||
wantUnknownPeers := func(want int64) {
|
||||
t.Helper()
|
||||
var got int64
|
||||
dl := time.Now().Add(5 * time.Second)
|
||||
for time.Now().Before(dl) {
|
||||
if got = peerGoneCountNotHere.Value(); got == want {
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -194,6 +215,30 @@ func TestSendRecv(t *testing.T) {
|
||||
recvNothing(0)
|
||||
recvNothing(1)
|
||||
|
||||
// Send messages to a non-existent node
|
||||
neKey := key.NewNode().Public()
|
||||
msg4 := []byte("not a CallMeMaybe->unknown destination\n")
|
||||
if err := clients[1].Send(neKey, msg4); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wantUnknownPeers(0)
|
||||
|
||||
callMe := neKey.AppendTo([]byte(disco.Magic))
|
||||
callMeHeader := make([]byte, disco.NonceLen)
|
||||
callMe = append(callMe, callMeHeader...)
|
||||
if err := clients[1].Send(neKey, callMe); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wantUnknownPeers(1)
|
||||
|
||||
// PeerGoneNotHere is rate-limited to 3 times a second
|
||||
for i := 0; i < 5; i++ {
|
||||
if err := clients[1].Send(neKey, callMe); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
wantUnknownPeers(3)
|
||||
|
||||
wantActive(3, 0)
|
||||
clients[0].NotePreferred(true)
|
||||
wantActive(3, 1)
|
||||
@ -595,10 +640,14 @@ func (tc *testClient) wantGone(t *testing.T, peer key.NodePublic) {
|
||||
}
|
||||
switch m := m.(type) {
|
||||
case PeerGoneMessage:
|
||||
got := key.NodePublic(m)
|
||||
got := key.NodePublic(m.Peer)
|
||||
if peer != got {
|
||||
t.Errorf("got gone message for %v; want gone for %v", tc.ts.keyName(got), tc.ts.keyName(peer))
|
||||
}
|
||||
reason := m.Reason
|
||||
if reason != PeerGoneReasonDisconnected {
|
||||
t.Errorf("got gone message for reason %v; wanted %v", reason, PeerGoneReasonDisconnected)
|
||||
}
|
||||
default:
|
||||
t.Fatalf("unexpected message type %T", m)
|
||||
}
|
||||
|
Reference in New Issue
Block a user