chore: add Coder service prefix to tailnet (#14943)

re: #14715

This PR introduces the Coder service prefix: `fd60:627a:a42b::/48` and refactors our existing code as calling the Tailscale service prefix explicitly (rather than implicitly).

Removes the unused `Addresses` agent option. All clients today assume they can compute the Agent's IP address based on its UUID, so an agent started with a custom address would break things.
This commit is contained in:
Spike Curtis
2024-10-04 10:04:10 +04:00
committed by GitHub
parent 68ec532ca7
commit 7d9f5ab81d
16 changed files with 120 additions and 75 deletions
+4 -11
View File
@@ -82,7 +82,6 @@ type Options struct {
SSHMaxTimeout time.Duration SSHMaxTimeout time.Duration
TailnetListenPort uint16 TailnetListenPort uint16
Subsystems []codersdk.AgentSubsystem Subsystems []codersdk.AgentSubsystem
Addresses []netip.Prefix
PrometheusRegistry *prometheus.Registry PrometheusRegistry *prometheus.Registry
ReportMetadataInterval time.Duration ReportMetadataInterval time.Duration
ServiceBannerRefreshInterval time.Duration ServiceBannerRefreshInterval time.Duration
@@ -180,7 +179,6 @@ func New(options Options) Agent {
announcementBannersRefreshInterval: options.ServiceBannerRefreshInterval, announcementBannersRefreshInterval: options.ServiceBannerRefreshInterval,
sshMaxTimeout: options.SSHMaxTimeout, sshMaxTimeout: options.SSHMaxTimeout,
subsystems: options.Subsystems, subsystems: options.Subsystems,
addresses: options.Addresses,
syscaller: options.Syscaller, syscaller: options.Syscaller,
modifiedProcs: options.ModifiedProcesses, modifiedProcs: options.ModifiedProcesses,
processManagementTick: options.ProcessManagementTick, processManagementTick: options.ProcessManagementTick,
@@ -250,7 +248,6 @@ type agent struct {
lifecycleLastReportedIndex int // Keeps track of the last lifecycle state we successfully reported. lifecycleLastReportedIndex int // Keeps track of the last lifecycle state we successfully reported.
network *tailnet.Conn network *tailnet.Conn
addresses []netip.Prefix
statsReporter *statsReporter statsReporter *statsReporter
logSender *agentsdk.LogSender logSender *agentsdk.LogSender
@@ -1112,15 +1109,11 @@ func (a *agent) updateCommandEnv(current []string) (updated []string, err error)
return updated, nil return updated, nil
} }
func (a *agent) wireguardAddresses(agentID uuid.UUID) []netip.Prefix { func (*agent) wireguardAddresses(agentID uuid.UUID) []netip.Prefix {
if len(a.addresses) == 0 { return []netip.Prefix{
return []netip.Prefix{ // This is the IP that should be used primarily.
// This is the IP that should be used primarily. tailnet.TailscaleServicePrefix.PrefixFromUUID(agentID),
netip.PrefixFrom(tailnet.IPFromUUID(agentID), 128),
}
} }
return a.addresses
} }
func (a *agent) trackGoroutine(fn func()) error { func (a *agent) trackGoroutine(fn func()) error {
+2 -2
View File
@@ -1880,7 +1880,7 @@ func TestAgent_UpdatedDERP(t *testing.T) {
// Setup a client connection. // Setup a client connection.
newClientConn := func(derpMap *tailcfg.DERPMap, name string) *workspacesdk.AgentConn { newClientConn := func(derpMap *tailcfg.DERPMap, name string) *workspacesdk.AgentConn {
conn, err := tailnet.NewConn(&tailnet.Options{ conn, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.RandomPrefix()},
DERPMap: derpMap, DERPMap: derpMap,
Logger: logger.Named(name), Logger: logger.Named(name),
}) })
@@ -2372,7 +2372,7 @@ func setupAgent(t *testing.T, metadata agentsdk.Manifest, ptyTimeout time.Durati
_ = agnt.Close() _ = agnt.Close()
}) })
conn, err := tailnet.NewConn(&tailnet.Options{ conn, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)}, Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.TailscaleServicePrefix.RandomAddr(), 128)},
DERPMap: metadata.DERPMap, DERPMap: metadata.DERPMap,
Logger: logger.Named("client"), Logger: logger.Named("client"),
}) })
+2 -2
View File
@@ -83,7 +83,7 @@ func TestDERP(t *testing.T) {
}, },
}, },
} }
w1IP := tailnet.IP() w1IP := tailnet.TailscaleServicePrefix.RandomAddr()
w1, err := tailnet.NewConn(&tailnet.Options{ w1, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(w1IP, 128)}, Addresses: []netip.Prefix{netip.PrefixFrom(w1IP, 128)},
Logger: logger.Named("w1"), Logger: logger.Named("w1"),
@@ -92,7 +92,7 @@ func TestDERP(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
w2, err := tailnet.NewConn(&tailnet.Options{ w2, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.RandomPrefix()},
Logger: logger.Named("w2"), Logger: logger.Named("w2"),
DERPMap: derpMap, DERPMap: derpMap,
}) })
+2 -2
View File
@@ -61,7 +61,7 @@ func NewServerTailnet(
) (*ServerTailnet, error) { ) (*ServerTailnet, error) {
logger = logger.Named("servertailnet") logger = logger.Named("servertailnet")
conn, err := tailnet.NewConn(&tailnet.Options{ conn, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.RandomPrefix()},
DERPForceWebSockets: derpForceWebSockets, DERPForceWebSockets: derpForceWebSockets,
Logger: logger, Logger: logger,
BlockEndpoints: blockEndpoints, BlockEndpoints: blockEndpoints,
@@ -352,7 +352,7 @@ func (s *ServerTailnet) ReverseProxy(targetURL, dashboardURL *url.URL, agentID u
// "localhost:port", causing connections to be shared across agents. // "localhost:port", causing connections to be shared across agents.
tgt := *targetURL tgt := *targetURL
_, port, _ := net.SplitHostPort(tgt.Host) _, port, _ := net.SplitHostPort(tgt.Host)
tgt.Host = net.JoinHostPort(tailnet.IPFromUUID(agentID).String(), port) tgt.Host = net.JoinHostPort(tailnet.TailscaleServicePrefix.AddrFromUUID(agentID).String(), port)
proxy := httputil.NewSingleHostReverseProxy(&tgt) proxy := httputil.NewSingleHostReverseProxy(&tgt)
proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, theErr error) { proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, theErr error) {
+3 -1
View File
@@ -186,7 +186,9 @@ func TestServerTailnet_ReverseProxy(t *testing.T) {
// Ensure the reverse proxy director rewrites the url host to the agent's IP. // Ensure the reverse proxy director rewrites the url host to the agent's IP.
rp.Director(req) rp.Director(req)
assert.Equal(t, assert.Equal(t,
fmt.Sprintf("[%s]:%d", tailnet.IPFromUUID(a.id).String(), workspacesdk.AgentHTTPAPIServerPort), fmt.Sprintf("[%s]:%d",
tailnet.TailscaleServicePrefix.AddrFromUUID(a.id).String(),
workspacesdk.AgentHTTPAPIServerPort),
req.URL.Host, req.URL.Host,
) )
}) })
+1 -1
View File
@@ -51,7 +51,7 @@ type AgentConnOptions struct {
} }
func (c *AgentConn) agentAddress() netip.Addr { func (c *AgentConn) agentAddress() netip.Addr {
return tailnet.IPFromUUID(c.opts.AgentID) return tailnet.TailscaleServicePrefix.AddrFromUUID(c.opts.AgentID)
} }
// AwaitReachable waits for the agent to be reachable. // AwaitReachable waits for the agent to be reachable.
+1 -1
View File
@@ -236,7 +236,7 @@ func (c *Client) DialAgent(dialCtx context.Context, agentID uuid.UUID, options *
CompressionMode: websocket.CompressionDisabled, CompressionMode: websocket.CompressionDisabled,
}) })
ip := tailnet.IP() ip := tailnet.TailscaleServicePrefix.RandomAddr()
var header http.Header var header http.Header
if headerTransport, ok := c.client.HTTPClient.Transport.(*codersdk.HeaderTransport); ok { if headerTransport, ok := c.client.HTTPClient.Transport.(*codersdk.HeaderTransport); ok {
header = headerTransport.Header header = headerTransport.Header
+3 -3
View File
@@ -120,7 +120,7 @@ func TestPGCoordinatorSingle_AgentInvalidIP(t *testing.T) {
defer agent.Close(ctx) defer agent.Close(ctx)
agent.UpdateNode(&proto.Node{ agent.UpdateNode(&proto.Node{
Addresses: []string{ Addresses: []string{
netip.PrefixFrom(agpl.IP(), 128).String(), agpl.TailscaleServicePrefix.RandomPrefix().String(),
}, },
PreferredDerp: 10, PreferredDerp: 10,
}) })
@@ -147,7 +147,7 @@ func TestPGCoordinatorSingle_AgentInvalidIPBits(t *testing.T) {
defer agent.Close(ctx) defer agent.Close(ctx)
agent.UpdateNode(&proto.Node{ agent.UpdateNode(&proto.Node{
Addresses: []string{ Addresses: []string{
netip.PrefixFrom(agpl.IPFromUUID(agent.ID), 64).String(), netip.PrefixFrom(agpl.TailscaleServicePrefix.AddrFromUUID(agent.ID), 64).String(),
}, },
PreferredDerp: 10, PreferredDerp: 10,
}) })
@@ -174,7 +174,7 @@ func TestPGCoordinatorSingle_AgentValidIP(t *testing.T) {
defer agent.Close(ctx) defer agent.Close(ctx)
agent.UpdateNode(&proto.Node{ agent.UpdateNode(&proto.Node{
Addresses: []string{ Addresses: []string{
netip.PrefixFrom(agpl.IPFromUUID(agent.ID), 128).String(), agpl.TailscaleServicePrefix.PrefixFromUUID(agent.ID).String(),
}, },
PreferredDerp: 10, PreferredDerp: 10,
}) })
+37 -17
View File
@@ -327,28 +327,48 @@ func NewConn(options *Options) (conn *Conn, err error) {
return server, nil return server, nil
} }
func maskUUID(uid uuid.UUID) uuid.UUID { type ServicePrefix [6]byte
// This is Tailscale's ephemeral service prefix. This can be changed easily
// later-on, because all of our nodes are ephemeral. var (
// fd7a:115c:a1e0 // TailscaleServicePrefix is the IPv6 prefix for all tailnet nodes since it was first added to
uid[0] = 0xfd // Coder. It is identical to the service prefix Tailscale.com uses. With the introduction of
uid[1] = 0x7a // CoderVPN, we would like to stop using the Tailscale prefix so that we don't conflict with
uid[2] = 0x11 // Tailscale if both are installed at the same time. However, there are a large number of agents
uid[3] = 0x5c // and clients using this prefix, so we need to carefully manage deprecation and eventual
uid[4] = 0xa1 // removal.
uid[5] = 0xe0 // fd7a:115c:a1e0:://48
TailscaleServicePrefix ServicePrefix = [6]byte{0xfd, 0x7a, 0x11, 0x5c, 0xa1, 0xe0}
// CoderServicePrefix is the Coder-specific IPv6 prefix for tailnet nodes, which we are in the
// process of migrating to. It allows Coder to run alongside Tailscale without conflicts even
// if both are set up as TUN interfaces into the OS (e.g. CoderVPN).
// fd60:627a:a42b::/48
CoderServicePrefix ServicePrefix = [6]byte{0xfd, 0x60, 0x62, 0x7a, 0xa4, 0x2b}
)
// maskUUID returns a new UUID with the first 6 bytes changed to the ServicePrefix
func (p ServicePrefix) maskUUID(uid uuid.UUID) uuid.UUID {
copy(uid[:], p[:])
return uid return uid
} }
// IP generates a random IP with a static service prefix. // RandomAddr returns a random IP address in the service prefix.
func IP() netip.Addr { func (p ServicePrefix) RandomAddr() netip.Addr {
uid := maskUUID(uuid.New()) return netip.AddrFrom16(p.maskUUID(uuid.New()))
return netip.AddrFrom16(uid)
} }
// IP generates a new IP from a UUID. // AddrFromUUID returns an IPv6 address corresponding to the given UUID in the service prefix.
func IPFromUUID(uid uuid.UUID) netip.Addr { func (p ServicePrefix) AddrFromUUID(uid uuid.UUID) netip.Addr {
return netip.AddrFrom16(maskUUID(uid)) return netip.AddrFrom16(p.maskUUID(uid))
}
// PrefixFromUUID returns a single IPv6 /128 prefix corresponding to the given UUID.
func (p ServicePrefix) PrefixFromUUID(uid uuid.UUID) netip.Prefix {
return netip.PrefixFrom(p.AddrFromUUID(uid), 128)
}
// RandomPrefix returns a single IPv6 /128 prefix within the service prefix.
func (p ServicePrefix) RandomPrefix() netip.Prefix {
return netip.PrefixFrom(p.RandomAddr(), 128)
} }
// Conn is an actively listening Wireguard connection. // Conn is an actively listening Wireguard connection.
+44 -15
View File
@@ -3,6 +3,7 @@ package tailnet_test
import ( import (
"context" "context"
"net/netip" "net/netip"
"strings"
"testing" "testing"
"time" "time"
@@ -30,7 +31,7 @@ func TestTailnet(t *testing.T) {
t.Parallel() t.Parallel()
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
conn, err := tailnet.NewConn(&tailnet.Options{ conn, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.RandomPrefix()},
Logger: logger.Named("w1"), Logger: logger.Named("w1"),
DERPMap: derpMap, DERPMap: derpMap,
}) })
@@ -42,7 +43,7 @@ func TestTailnet(t *testing.T) {
t.Parallel() t.Parallel()
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
ctx := testutil.Context(t, testutil.WaitLong) ctx := testutil.Context(t, testutil.WaitLong)
w1IP := tailnet.IP() w1IP := tailnet.TailscaleServicePrefix.RandomAddr()
w1, err := tailnet.NewConn(&tailnet.Options{ w1, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(w1IP, 128)}, Addresses: []netip.Prefix{netip.PrefixFrom(w1IP, 128)},
Logger: logger.Named("w1"), Logger: logger.Named("w1"),
@@ -51,7 +52,7 @@ func TestTailnet(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
w2, err := tailnet.NewConn(&tailnet.Options{ w2, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.RandomPrefix()},
Logger: logger.Named("w2"), Logger: logger.Named("w2"),
DERPMap: derpMap, DERPMap: derpMap,
}) })
@@ -106,7 +107,7 @@ func TestTailnet(t *testing.T) {
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
ctx := testutil.Context(t, testutil.WaitMedium) ctx := testutil.Context(t, testutil.WaitMedium)
w1IP := tailnet.IP() w1IP := tailnet.TailscaleServicePrefix.RandomAddr()
derpMap := tailnettest.RunDERPOnlyWebSockets(t) derpMap := tailnettest.RunDERPOnlyWebSockets(t)
w1, err := tailnet.NewConn(&tailnet.Options{ w1, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(w1IP, 128)}, Addresses: []netip.Prefix{netip.PrefixFrom(w1IP, 128)},
@@ -117,7 +118,7 @@ func TestTailnet(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
w2, err := tailnet.NewConn(&tailnet.Options{ w2, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.RandomPrefix()},
Logger: logger.Named("w2"), Logger: logger.Named("w2"),
DERPMap: derpMap, DERPMap: derpMap,
BlockEndpoints: true, BlockEndpoints: true,
@@ -168,7 +169,7 @@ func TestTailnet(t *testing.T) {
t.Parallel() t.Parallel()
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
ctx := testutil.Context(t, testutil.WaitLong) ctx := testutil.Context(t, testutil.WaitLong)
w1IP := tailnet.IP() w1IP := tailnet.TailscaleServicePrefix.RandomAddr()
w1, err := tailnet.NewConn(&tailnet.Options{ w1, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(w1IP, 128)}, Addresses: []netip.Prefix{netip.PrefixFrom(w1IP, 128)},
Logger: logger.Named("w1"), Logger: logger.Named("w1"),
@@ -177,7 +178,7 @@ func TestTailnet(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
w2, err := tailnet.NewConn(&tailnet.Options{ w2, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.RandomPrefix()},
Logger: logger.Named("w2"), Logger: logger.Named("w2"),
DERPMap: derpMap, DERPMap: derpMap,
}) })
@@ -211,7 +212,7 @@ func TestTailnet(t *testing.T) {
t.Parallel() t.Parallel()
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
ctx := testutil.Context(t, testutil.WaitLong) ctx := testutil.Context(t, testutil.WaitLong)
w1IP := tailnet.IP() w1IP := tailnet.TailscaleServicePrefix.RandomAddr()
w1, err := tailnet.NewConn(&tailnet.Options{ w1, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(w1IP, 128)}, Addresses: []netip.Prefix{netip.PrefixFrom(w1IP, 128)},
Logger: logger.Named("w1"), Logger: logger.Named("w1"),
@@ -221,7 +222,7 @@ func TestTailnet(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
w2, err := tailnet.NewConn(&tailnet.Options{ w2, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.RandomPrefix()},
Logger: logger.Named("w2"), Logger: logger.Named("w2"),
DERPMap: derpMap, DERPMap: derpMap,
BlockEndpoints: true, BlockEndpoints: true,
@@ -261,7 +262,7 @@ func TestConn_PreferredDERP(t *testing.T) {
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
derpMap, _ := tailnettest.RunDERPAndSTUN(t) derpMap, _ := tailnettest.RunDERPAndSTUN(t)
conn, err := tailnet.NewConn(&tailnet.Options{ conn, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.RandomPrefix()},
Logger: logger.Named("w1"), Logger: logger.Named("w1"),
DERPMap: derpMap, DERPMap: derpMap,
}) })
@@ -290,7 +291,7 @@ func TestConn_UpdateDERP(t *testing.T) {
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
derpMap1, _ := tailnettest.RunDERPAndSTUN(t) derpMap1, _ := tailnettest.RunDERPAndSTUN(t)
ip := tailnet.IP() ip := tailnet.TailscaleServicePrefix.RandomAddr()
conn, err := tailnet.NewConn(&tailnet.Options{ conn, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(ip, 128)}, Addresses: []netip.Prefix{netip.PrefixFrom(ip, 128)},
Logger: logger.Named("w1"), Logger: logger.Named("w1"),
@@ -320,7 +321,7 @@ func TestConn_UpdateDERP(t *testing.T) {
// Connect from a different client. // Connect from a different client.
client1, err := tailnet.NewConn(&tailnet.Options{ client1, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.RandomPrefix()},
Logger: logger.Named("client1"), Logger: logger.Named("client1"),
DERPMap: derpMap1, DERPMap: derpMap1,
BlockEndpoints: true, BlockEndpoints: true,
@@ -394,7 +395,7 @@ parentLoop:
// Connect from a different different client with up-to-date derp map and // Connect from a different different client with up-to-date derp map and
// nodes. // nodes.
client2, err := tailnet.NewConn(&tailnet.Options{ client2, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.RandomPrefix()},
Logger: logger.Named("client2"), Logger: logger.Named("client2"),
DERPMap: derpMap2, DERPMap: derpMap2,
BlockEndpoints: true, BlockEndpoints: true,
@@ -425,7 +426,7 @@ func TestConn_BlockEndpoints(t *testing.T) {
derpMap, _ := tailnettest.RunDERPAndSTUN(t) derpMap, _ := tailnettest.RunDERPAndSTUN(t)
// Setup conn 1. // Setup conn 1.
ip1 := tailnet.IP() ip1 := tailnet.TailscaleServicePrefix.RandomAddr()
conn1, err := tailnet.NewConn(&tailnet.Options{ conn1, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(ip1, 128)}, Addresses: []netip.Prefix{netip.PrefixFrom(ip1, 128)},
Logger: logger.Named("w1"), Logger: logger.Named("w1"),
@@ -439,7 +440,7 @@ func TestConn_BlockEndpoints(t *testing.T) {
}() }()
// Setup conn 2. // Setup conn 2.
ip2 := tailnet.IP() ip2 := tailnet.TailscaleServicePrefix.RandomAddr()
conn2, err := tailnet.NewConn(&tailnet.Options{ conn2, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(ip2, 128)}, Addresses: []netip.Prefix{netip.PrefixFrom(ip2, 128)},
Logger: logger.Named("w2"), Logger: logger.Named("w2"),
@@ -492,3 +493,31 @@ func stitch(t *testing.T, dst, src *tailnet.Conn) {
assert.NoError(t, err) assert.NoError(t, err)
}) })
} }
func TestTailscaleServicePrefix(t *testing.T) {
t.Parallel()
a := tailnet.TailscaleServicePrefix.RandomAddr()
require.True(t, strings.HasPrefix(a.String(), "fd7a:115c:a1e0"))
p := tailnet.TailscaleServicePrefix.RandomPrefix()
require.True(t, strings.HasPrefix(p.String(), "fd7a:115c:a1e0"))
require.True(t, strings.HasSuffix(p.String(), "/128"))
u := uuid.MustParse("aaaaaaaa-aaaa-aaaa-aaaa-123456789abc")
a = tailnet.TailscaleServicePrefix.AddrFromUUID(u)
require.Equal(t, "fd7a:115c:a1e0:aaaa:aaaa:1234:5678:9abc", a.String())
p = tailnet.TailscaleServicePrefix.PrefixFromUUID(u)
require.Equal(t, "fd7a:115c:a1e0:aaaa:aaaa:1234:5678:9abc/128", p.String())
}
func TestCoderServicePrefix(t *testing.T) {
t.Parallel()
a := tailnet.CoderServicePrefix.RandomAddr()
require.True(t, strings.HasPrefix(a.String(), "fd60:627a:a42b"))
p := tailnet.CoderServicePrefix.RandomPrefix()
require.True(t, strings.HasPrefix(p.String(), "fd60:627a:a42b"))
require.True(t, strings.HasSuffix(p.String(), "/128"))
u := uuid.MustParse("aaaaaaaa-aaaa-aaaa-aaaa-123456789abc")
a = tailnet.CoderServicePrefix.AddrFromUUID(u)
require.Equal(t, "fd60:627a:a42b:aaaa:aaaa:1234:5678:9abc", a.String())
p = tailnet.CoderServicePrefix.PrefixFromUUID(u)
require.Equal(t, "fd60:627a:a42b:aaaa:aaaa:1234:5678:9abc/128", p.String())
}
+6 -5
View File
@@ -40,7 +40,7 @@ func TestCoordinator(t *testing.T) {
client := test.NewClient(ctx, t, coordinator, "client", uuid.New()) client := test.NewClient(ctx, t, coordinator, "client", uuid.New())
defer client.Close(ctx) defer client.Close(ctx)
client.UpdateNode(&proto.Node{ client.UpdateNode(&proto.Node{
Addresses: []string{netip.PrefixFrom(tailnet.IP(), 128).String()}, Addresses: []string{tailnet.TailscaleServicePrefix.RandomPrefix().String()},
PreferredDerp: 10, PreferredDerp: 10,
}) })
require.Eventually(t, func() bool { require.Eventually(t, func() bool {
@@ -63,7 +63,7 @@ func TestCoordinator(t *testing.T) {
client.UpdateNode(&proto.Node{ client.UpdateNode(&proto.Node{
Addresses: []string{ Addresses: []string{
netip.PrefixFrom(tailnet.IP(), 64).String(), netip.PrefixFrom(tailnet.TailscaleServicePrefix.RandomAddr(), 64).String(),
}, },
PreferredDerp: 10, PreferredDerp: 10,
}) })
@@ -84,7 +84,7 @@ func TestCoordinator(t *testing.T) {
defer agent.Close(ctx) defer agent.Close(ctx)
agent.UpdateNode(&proto.Node{ agent.UpdateNode(&proto.Node{
Addresses: []string{ Addresses: []string{
netip.PrefixFrom(tailnet.IPFromUUID(agent.ID), 128).String(), tailnet.TailscaleServicePrefix.PrefixFromUUID(agent.ID).String(),
}, },
PreferredDerp: 10, PreferredDerp: 10,
}) })
@@ -106,7 +106,7 @@ func TestCoordinator(t *testing.T) {
defer agent.Close(ctx) defer agent.Close(ctx)
agent.UpdateNode(&proto.Node{ agent.UpdateNode(&proto.Node{
Addresses: []string{ Addresses: []string{
netip.PrefixFrom(tailnet.IP(), 128).String(), tailnet.TailscaleServicePrefix.RandomPrefix().String(),
}, },
PreferredDerp: 10, PreferredDerp: 10,
}) })
@@ -126,7 +126,8 @@ func TestCoordinator(t *testing.T) {
defer agent.Close(ctx) defer agent.Close(ctx)
agent.UpdateNode(&proto.Node{ agent.UpdateNode(&proto.Node{
Addresses: []string{ Addresses: []string{
netip.PrefixFrom(tailnet.IPFromUUID(agent.ID), 64).String(), netip.PrefixFrom(
tailnet.TailscaleServicePrefix.AddrFromUUID(agent.ID), 64).String(),
}, },
PreferredDerp: 10, PreferredDerp: 10,
}) })
+5 -5
View File
@@ -18,7 +18,7 @@ func TestTelemetryStore(t *testing.T) {
t.Run("CreateEvent", func(t *testing.T) { t.Run("CreateEvent", func(t *testing.T) {
t.Parallel() t.Parallel()
remotePrefix := netip.PrefixFrom(IP(), 128) remotePrefix := TailscaleServicePrefix.RandomPrefix()
remoteIP := remotePrefix.Addr() remoteIP := remotePrefix.Addr()
application := "test" application := "test"
@@ -31,16 +31,16 @@ func TestTelemetryStore(t *testing.T) {
{ {
ID: 1, ID: 1,
Addresses: []netip.Prefix{ Addresses: []netip.Prefix{
netip.PrefixFrom(IP(), 128), TailscaleServicePrefix.RandomPrefix(),
netip.PrefixFrom(IP(), 128), TailscaleServicePrefix.RandomPrefix(),
}, },
}, },
{ {
ID: 2, ID: 2,
Addresses: []netip.Prefix{ Addresses: []netip.Prefix{
remotePrefix, remotePrefix,
netip.PrefixFrom(IP(), 128), TailscaleServicePrefix.RandomPrefix(),
netip.PrefixFrom(IP(), 128), TailscaleServicePrefix.RandomPrefix(),
}, },
}, },
}, },
+4 -4
View File
@@ -373,7 +373,7 @@ http {
// and creates a tailnet.Conn which will only use DERP to connect to the peer. // and creates a tailnet.Conn which will only use DERP to connect to the peer.
func StartClientDERP(t *testing.T, logger slog.Logger, serverURL *url.URL, derpMap *tailcfg.DERPMap, me, peer Client) *tailnet.Conn { func StartClientDERP(t *testing.T, logger slog.Logger, serverURL *url.URL, derpMap *tailcfg.DERPMap, me, peer Client) *tailnet.Conn {
return startClientOptions(t, logger, serverURL, me, peer, &tailnet.Options{ return startClientOptions(t, logger, serverURL, me, peer, &tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IPFromUUID(me.ID), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.PrefixFromUUID(me.ID)},
DERPMap: derpMap, DERPMap: derpMap,
BlockEndpoints: true, BlockEndpoints: true,
Logger: logger, Logger: logger,
@@ -389,7 +389,7 @@ func StartClientDERP(t *testing.T, logger slog.Logger, serverURL *url.URL, derpM
// only use DERP WebSocket fallback. // only use DERP WebSocket fallback.
func StartClientDERPWebSockets(t *testing.T, logger slog.Logger, serverURL *url.URL, derpMap *tailcfg.DERPMap, me, peer Client) *tailnet.Conn { func StartClientDERPWebSockets(t *testing.T, logger slog.Logger, serverURL *url.URL, derpMap *tailcfg.DERPMap, me, peer Client) *tailnet.Conn {
return startClientOptions(t, logger, serverURL, me, peer, &tailnet.Options{ return startClientOptions(t, logger, serverURL, me, peer, &tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IPFromUUID(me.ID), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.PrefixFromUUID(me.ID)},
DERPMap: derpMap, DERPMap: derpMap,
BlockEndpoints: true, BlockEndpoints: true,
Logger: logger, Logger: logger,
@@ -406,7 +406,7 @@ func StartClientDERPWebSockets(t *testing.T, logger slog.Logger, serverURL *url.
// connection to be established between the two peers. // connection to be established between the two peers.
func StartClientDirect(t *testing.T, logger slog.Logger, serverURL *url.URL, derpMap *tailcfg.DERPMap, me, peer Client) *tailnet.Conn { func StartClientDirect(t *testing.T, logger slog.Logger, serverURL *url.URL, derpMap *tailcfg.DERPMap, me, peer Client) *tailnet.Conn {
conn := startClientOptions(t, logger, serverURL, me, peer, &tailnet.Options{ conn := startClientOptions(t, logger, serverURL, me, peer, &tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IPFromUUID(me.ID), 128)}, Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.PrefixFromUUID(me.ID)},
DERPMap: derpMap, DERPMap: derpMap,
BlockEndpoints: false, BlockEndpoints: false,
Logger: logger, Logger: logger,
@@ -418,7 +418,7 @@ func StartClientDirect(t *testing.T, logger slog.Logger, serverURL *url.URL, der
}) })
// Wait for direct connection to be established. // Wait for direct connection to be established.
peerIP := tailnet.IPFromUUID(peer.ID) peerIP := tailnet.TailscaleServicePrefix.AddrFromUUID(peer.ID)
require.Eventually(t, func() bool { require.Eventually(t, func() bool {
t.Log("attempting ping to peer to judge direct connection") t.Log("attempting ping to peer to judge direct connection")
ctx := testutil.Context(t, testutil.WaitShort) ctx := testutil.Context(t, testutil.WaitShort)
+1 -1
View File
@@ -267,7 +267,7 @@ func handleTestSubprocess(t *testing.T) {
if me.ShouldRunTests { if me.ShouldRunTests {
// Wait for connectivity. // Wait for connectivity.
peerIP := tailnet.IPFromUUID(peer.ID) peerIP := tailnet.TailscaleServicePrefix.AddrFromUUID(peer.ID)
if !conn.AwaitReachable(testutil.Context(t, testutil.WaitLong), peerIP) { if !conn.AwaitReachable(testutil.Context(t, testutil.WaitLong), peerIP) {
t.Fatalf("peer %v did not become reachable", peerIP) t.Fatalf("peer %v did not become reachable", peerIP)
} }
+4 -4
View File
@@ -48,13 +48,13 @@ func TestSuite(t *testing.T, _ slog.Logger, serverURL *url.URL, conn *tailnet.Co
t.Run("Connectivity", func(t *testing.T) { t.Run("Connectivity", func(t *testing.T) {
t.Parallel() t.Parallel()
peerIP := tailnet.IPFromUUID(peer.ID) peerIP := tailnet.TailscaleServicePrefix.AddrFromUUID(peer.ID)
_, _, _, err := conn.Ping(testutil.Context(t, testutil.WaitLong), peerIP) _, _, _, err := conn.Ping(testutil.Context(t, testutil.WaitLong), peerIP)
require.NoError(t, err, "ping peer") require.NoError(t, err, "ping peer")
}) })
t.Run("RestartDERP", func(t *testing.T) { t.Run("RestartDERP", func(t *testing.T) {
peerIP := tailnet.IPFromUUID(peer.ID) peerIP := tailnet.TailscaleServicePrefix.AddrFromUUID(peer.ID)
_, _, _, err := conn.Ping(testutil.Context(t, testutil.WaitLong), peerIP) _, _, _, err := conn.Ping(testutil.Context(t, testutil.WaitLong), peerIP)
require.NoError(t, err, "ping peer") require.NoError(t, err, "ping peer")
sendRestart(t, serverURL, true, false) sendRestart(t, serverURL, true, false)
@@ -63,7 +63,7 @@ func TestSuite(t *testing.T, _ slog.Logger, serverURL *url.URL, conn *tailnet.Co
}) })
t.Run("RestartCoordinator", func(t *testing.T) { t.Run("RestartCoordinator", func(t *testing.T) {
peerIP := tailnet.IPFromUUID(peer.ID) peerIP := tailnet.TailscaleServicePrefix.AddrFromUUID(peer.ID)
_, _, _, err := conn.Ping(testutil.Context(t, testutil.WaitLong), peerIP) _, _, _, err := conn.Ping(testutil.Context(t, testutil.WaitLong), peerIP)
require.NoError(t, err, "ping peer") require.NoError(t, err, "ping peer")
sendRestart(t, serverURL, false, true) sendRestart(t, serverURL, false, true)
@@ -72,7 +72,7 @@ func TestSuite(t *testing.T, _ slog.Logger, serverURL *url.URL, conn *tailnet.Co
}) })
t.Run("RestartBoth", func(t *testing.T) { t.Run("RestartBoth", func(t *testing.T) {
peerIP := tailnet.IPFromUUID(peer.ID) peerIP := tailnet.TailscaleServicePrefix.AddrFromUUID(peer.ID)
_, _, _, err := conn.Ping(testutil.Context(t, testutil.WaitLong), peerIP) _, _, _, err := conn.Ping(testutil.Context(t, testutil.WaitLong), peerIP)
require.NoError(t, err, "ping peer") require.NoError(t, err, "ping peer")
sendRestart(t, serverURL, true, true) sendRestart(t, serverURL, true, true)
+1 -1
View File
@@ -80,7 +80,7 @@ func (a AgentCoordinateeAuth) Authorize(req *proto.CoordinateRequest) error {
return xerrors.Errorf("invalid address bits, expected 128, got %d", pre.Bits()) return xerrors.Errorf("invalid address bits, expected 128, got %d", pre.Bits())
} }
if IPFromUUID(a.ID).Compare(pre.Addr()) != 0 && if TailscaleServicePrefix.AddrFromUUID(a.ID).Compare(pre.Addr()) != 0 &&
legacyWorkspaceAgentIP.Compare(pre.Addr()) != 0 { legacyWorkspaceAgentIP.Compare(pre.Addr()) != 0 {
return xerrors.Errorf("invalid node address, got %s", pre.Addr().String()) return xerrors.Errorf("invalid node address, got %s", pre.Addr().String())
} }