From 027959c1ab249afc7d37340bf12de66eeb2ec6ac Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 31 Oct 2024 07:56:58 -0700 Subject: [PATCH] prober: support probing DERP regions with nodes in mixed VPCs Updates tailscale/corp#24232 Change-Id: Ief50a337b61b5791f03d48d7274f4e9c25e5656a Signed-off-by: Brad Fitzpatrick --- prober/derp.go | 27 +++++++++++++++++++++++++++ prober/derp_test.go | 18 +++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/prober/derp.go b/prober/derp.go index 0dadbe8c2..6a2069c3f 100644 --- a/prober/derp.go +++ b/prober/derp.go @@ -172,6 +172,15 @@ func (d *derpProber) probeMapFn(ctx context.Context) error { } for _, to := range region.Nodes { + if !inSameVPC(server, to) { + // This pair of nodes in the region are in different VPCs; don't expect + // them to be meshed. In the general case, the DERPMap data structure and client + // don't support such a region configuration. This is a special case for + // Tailscale's probers being able to monitor a meta DERP map that's a superset + // of multiple independent DERP maps. + continue + } + if d.meshInterval > 0 { n := fmt.Sprintf("derp/%s/%s/%s/mesh", region.RegionCode, server.Name, to.Name) wantProbes[n] = true @@ -204,6 +213,24 @@ func (d *derpProber) probeMapFn(ctx context.Context) error { return nil } +func inSameVPC(a, b *tailcfg.DERPNode) bool { + return vpcName(a.Name) == vpcName(b.Name) +} + +// vpcName returns the name of a VPC that a DERP Node is running +// in as a function of its DERPNode.Name. +// +// This is a naming convention for the Tailscale-run DERP nodes only +// and is not a thing that's supported by clients. See the comments +// at the caller of this. +func vpcName(n string) string { + _, name, ok := strings.Cut(n, "-vpc") + if !ok || name == "" { + return "default" + } + return name +} + // probeMesh returs a probe class that sends a test packet through a pair of DERP // servers (or just one server, if 'from' and 'to' are the same). 'from' and 'to' // are expected to be names (DERPNode.Name) of two DERP servers in the same region. diff --git a/prober/derp_test.go b/prober/derp_test.go index a34292a23..70071477e 100644 --- a/prober/derp_test.go +++ b/prober/derp_test.go @@ -21,7 +21,7 @@ "tailscale.com/types/key" ) -func TestDerpProber(t *testing.T) { +func TestDERPProber(t *testing.T) { dm := &tailcfg.DERPMap{ Regions: map[int]*tailcfg.DERPRegion{ 0: { @@ -210,3 +210,19 @@ func Test_packetsForSize(t *testing.T) { }) } } + +func TestInSameVPC(t *testing.T) { + tests := []struct { + a, b string + want bool + }{ + {"foo", "bar", true}, + {"foo-vpc1", "bar-vpc1", true}, + {"foo-vpc1", "bar-vpc2", false}, + } + for _, tt := range tests { + if got := inSameVPC(&tailcfg.DERPNode{Name: tt.a}, &tailcfg.DERPNode{Name: tt.b}); got != tt.want { + t.Errorf("inSameVPC(%q, %q) = %v; want %v", tt.a, tt.b, got, tt.want) + } + } +}