diff --git a/tailnet/test/integration/integration.go b/tailnet/test/integration/integration.go index fdf0d9a37f..bc9c3493e3 100644 --- a/tailnet/test/integration/integration.go +++ b/tailnet/test/integration/integration.go @@ -32,6 +32,7 @@ import ( "github.com/coder/coder/v2/coderd/tracing" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/tailnet" + "github.com/coder/coder/v2/testutil" ) // IDs used in tests. @@ -186,6 +187,42 @@ func StartClientDERPWebSockets(t *testing.T, logger slog.Logger, serverURL *url. }) } +// StartClientDirect does the same thing as StartClientDERP but disables +// BlockEndpoints (which enables Direct connections), and waits for a direct +// connection to be established between the two peers. +func StartClientDirect(t *testing.T, logger slog.Logger, serverURL *url.URL, myID, peerID uuid.UUID) *tailnet.Conn { + conn := startClientOptions(t, logger, serverURL, myID, peerID, &tailnet.Options{ + Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IPFromUUID(myID), 128)}, + DERPMap: basicDERPMap(t, serverURL), + BlockEndpoints: false, + Logger: logger, + DERPForceWebSockets: true, + // These tests don't have internet connection, so we need to force + // magicsock to do anything. + ForceNetworkUp: true, + }) + + // Wait for direct connection to be established. + peerIP := tailnet.IPFromUUID(peerID) + require.Eventually(t, func() bool { + t.Log("attempting ping to peer to judge direct connection") + ctx := testutil.Context(t, testutil.WaitShort) + _, p2p, pong, err := conn.Ping(ctx, peerIP) + if err != nil { + t.Logf("ping failed: %v", err) + return false + } + if !p2p { + t.Log("ping succeeded, but not direct yet") + return false + } + t.Logf("ping succeeded, direct connection established via %s", pong.Endpoint) + return true + }, testutil.WaitLong, testutil.IntervalMedium) + + return conn +} + type ClientStarter struct { Options *tailnet.Options } diff --git a/tailnet/test/integration/integration_test.go b/tailnet/test/integration/integration_test.go index dcd64b9343..0b4cf38fb3 100644 --- a/tailnet/test/integration/integration_test.go +++ b/tailnet/test/integration/integration_test.go @@ -86,6 +86,16 @@ var topologies = []integration.TestTopology{ StartClient: integration.StartClientDERP, RunTests: integration.TestSuite, }, + { + // Test that direct over "easy" NAT works. This should use local + // endpoints to connect as routing is enabled between client 1 and + // client 2. + Name: "EasyNATDirect", + SetupNetworking: integration.SetupNetworkingEasyNAT, + ServerOptions: integration.ServerOptions{}, + StartClient: integration.StartClientDirect, + RunTests: integration.TestSuite, + }, { // Test that DERP over WebSocket (as well as DERPForceWebSockets works). // This does not test the actual DERP failure detection code and