Skip to content

Commit 23bedfa

Browse files
committed
feat: vpn uses WorkspaceHostnameSuffix for DNS names
1 parent 6cee450 commit 23bedfa

File tree

5 files changed

+215
-153
lines changed

5 files changed

+215
-153
lines changed

codersdk/workspacesdk/workspacesdk.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ type AgentConnectionInfo struct {
143143
DERPMap *tailcfg.DERPMap `json:"derp_map"`
144144
DERPForceWebSockets bool `json:"derp_force_websockets"`
145145
DisableDirectConnections bool `json:"disable_direct_connections"`
146-
HostnameSuffix string `json:"hostname_suffix"`
146+
HostnameSuffix string `json:"hostname_suffix,omitempty"`
147147
}
148148

149149
func (c *Client) AgentConnectionInfoGeneric(ctx context.Context) (AgentConnectionInfo, error) {

tailnet/controllers.go

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -863,11 +863,12 @@ func (r *basicResumeTokenRefresher) refresh() {
863863
}
864864

865865
type TunnelAllWorkspaceUpdatesController struct {
866-
coordCtrl *TunnelSrcCoordController
867-
dnsHostSetter DNSHostsSetter
868-
updateHandler UpdatesHandler
869-
ownerUsername string
870-
logger slog.Logger
866+
coordCtrl *TunnelSrcCoordController
867+
dnsHostSetter DNSHostsSetter
868+
dnsNameOptions DNSNameOptions
869+
updateHandler UpdatesHandler
870+
ownerUsername string
871+
logger slog.Logger
871872

872873
mu sync.Mutex
873874
updater *tunnelUpdater
@@ -882,37 +883,39 @@ type Workspace struct {
882883
agents map[uuid.UUID]*Agent
883884
}
884885

886+
type DNSNameOptions struct {
887+
Suffix string
888+
}
889+
885890
// updateDNSNames updates the DNS names for all agents in the workspace.
886891
// DNS hosts must be all lowercase, or the resolver won't be able to find them.
887892
// Usernames are globally unique & case-insensitive.
888893
// Workspace names are unique per-user & case-insensitive.
889894
// Agent names are unique per-workspace & case-insensitive.
890-
func (w *Workspace) updateDNSNames() error {
895+
func (w *Workspace) updateDNSNames(options DNSNameOptions) error {
891896
wsName := strings.ToLower(w.Name)
892897
username := strings.ToLower(w.ownerUsername)
893898
for id, a := range w.agents {
894899
agentName := strings.ToLower(a.Name)
895900
names := make(map[dnsname.FQDN][]netip.Addr)
896901
// TODO: technically, DNS labels cannot start with numbers, but the rules are often not
897902
// strictly enforced.
898-
fqdn, err := dnsname.ToFQDN(fmt.Sprintf("%s.%s.me.coder.", agentName, wsName))
903+
fqdn, err := dnsname.ToFQDN(fmt.Sprintf("%s.%s.me.%s.", agentName, wsName, options.Suffix))
899904
if err != nil {
900905
return err
901906
}
902907
names[fqdn] = []netip.Addr{CoderServicePrefix.AddrFromUUID(a.ID)}
903-
fqdn, err = dnsname.ToFQDN(fmt.Sprintf("%s.%s.%s.coder.", agentName, wsName, username))
908+
fqdn, err = dnsname.ToFQDN(fmt.Sprintf("%s.%s.%s.%s.", agentName, wsName, username, options.Suffix))
904909
if err != nil {
905910
return err
906911
}
907912
names[fqdn] = []netip.Addr{CoderServicePrefix.AddrFromUUID(a.ID)}
908913
if len(w.agents) == 1 {
909-
fqdn, err := dnsname.ToFQDN(fmt.Sprintf("%s.coder.", wsName))
914+
fqdn, err = dnsname.ToFQDN(fmt.Sprintf("%s.%s.", wsName, options.Suffix))
910915
if err != nil {
911916
return err
912917
}
913-
for _, a := range w.agents {
914-
names[fqdn] = []netip.Addr{CoderServicePrefix.AddrFromUUID(a.ID)}
915-
}
918+
names[fqdn] = []netip.Addr{CoderServicePrefix.AddrFromUUID(a.ID)}
916919
}
917920
a.Hosts = names
918921
w.agents[id] = a
@@ -949,6 +952,7 @@ func (t *TunnelAllWorkspaceUpdatesController) New(client WorkspaceUpdatesClient)
949952
logger: t.logger,
950953
coordCtrl: t.coordCtrl,
951954
dnsHostsSetter: t.dnsHostSetter,
955+
dnsNameOptions: t.dnsNameOptions,
952956
updateHandler: t.updateHandler,
953957
ownerUsername: t.ownerUsername,
954958
recvLoopDone: make(chan struct{}),
@@ -995,6 +999,7 @@ type tunnelUpdater struct {
995999
updateHandler UpdatesHandler
9961000
ownerUsername string
9971001
recvLoopDone chan struct{}
1002+
dnsNameOptions DNSNameOptions
9981003

9991004
sync.Mutex
10001005
workspaces map[uuid.UUID]*Workspace
@@ -1249,7 +1254,7 @@ func (t *tunnelUpdater) allAgentIDsLocked() []uuid.UUID {
12491254
func (t *tunnelUpdater) updateDNSNamesLocked() map[dnsname.FQDN][]netip.Addr {
12501255
names := make(map[dnsname.FQDN][]netip.Addr)
12511256
for _, w := range t.workspaces {
1252-
err := w.updateDNSNames()
1257+
err := w.updateDNSNames(t.dnsNameOptions)
12531258
if err != nil {
12541259
// This should never happen in production, because converting the FQDN only fails
12551260
// if names are too long, and we put strict length limits on agent, workspace, and user
@@ -1272,10 +1277,11 @@ type TunnelAllOption func(t *TunnelAllWorkspaceUpdatesController)
12721277

12731278
// WithDNS configures the tunnelAllWorkspaceUpdatesController to set DNS names for all workspaces
12741279
// and agents it learns about.
1275-
func WithDNS(d DNSHostsSetter, ownerUsername string) TunnelAllOption {
1280+
func WithDNS(d DNSHostsSetter, ownerUsername string, options DNSNameOptions) TunnelAllOption {
12761281
return func(t *TunnelAllWorkspaceUpdatesController) {
12771282
t.dnsHostSetter = d
12781283
t.ownerUsername = ownerUsername
1284+
t.dnsNameOptions = options
12791285
}
12801286
}
12811287

@@ -1291,7 +1297,11 @@ func WithHandler(h UpdatesHandler) TunnelAllOption {
12911297
func NewTunnelAllWorkspaceUpdatesController(
12921298
logger slog.Logger, c *TunnelSrcCoordController, opts ...TunnelAllOption,
12931299
) *TunnelAllWorkspaceUpdatesController {
1294-
t := &TunnelAllWorkspaceUpdatesController{logger: logger, coordCtrl: c}
1300+
t := &TunnelAllWorkspaceUpdatesController{
1301+
logger: logger,
1302+
coordCtrl: c,
1303+
dnsNameOptions: DNSNameOptions{"coder"},
1304+
}
12951305
for _, opt := range opts {
12961306
opt(t)
12971307
}

tailnet/controllers_test.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,7 +1521,7 @@ func TestTunnelAllWorkspaceUpdatesController_Initial(t *testing.T) {
15211521
fUH := newFakeUpdateHandler(ctx, t)
15221522
fDNS := newFakeDNSSetter(ctx, t)
15231523
coordC, updateC, updateCtrl := setupConnectedAllWorkspaceUpdatesController(ctx, t, logger,
1524-
tailnet.WithDNS(fDNS, "testy"),
1524+
tailnet.WithDNS(fDNS, "testy", tailnet.DNSNameOptions{Suffix: "mctest"}),
15251525
tailnet.WithHandler(fUH),
15261526
)
15271527

@@ -1563,13 +1563,13 @@ func TestTunnelAllWorkspaceUpdatesController_Initial(t *testing.T) {
15631563

15641564
// Also triggers setting DNS hosts
15651565
expectedDNS := map[dnsname.FQDN][]netip.Addr{
1566-
"w1a1.w1.me.coder.": {ws1a1IP},
1567-
"w2a1.w2.me.coder.": {w2a1IP},
1568-
"w2a2.w2.me.coder.": {w2a2IP},
1569-
"w1a1.w1.testy.coder.": {ws1a1IP},
1570-
"w2a1.w2.testy.coder.": {w2a1IP},
1571-
"w2a2.w2.testy.coder.": {w2a2IP},
1572-
"w1.coder.": {ws1a1IP},
1566+
"w1a1.w1.me.mctest.": {ws1a1IP},
1567+
"w2a1.w2.me.mctest.": {w2a1IP},
1568+
"w2a2.w2.me.mctest.": {w2a2IP},
1569+
"w1a1.w1.testy.mctest.": {ws1a1IP},
1570+
"w2a1.w2.testy.mctest.": {w2a1IP},
1571+
"w2a2.w2.testy.mctest.": {w2a2IP},
1572+
"w1.mctest.": {ws1a1IP},
15731573
}
15741574
dnsCall := testutil.RequireRecvCtx(ctx, t, fDNS.calls)
15751575
require.Equal(t, expectedDNS, dnsCall.hosts)
@@ -1584,23 +1584,23 @@ func TestTunnelAllWorkspaceUpdatesController_Initial(t *testing.T) {
15841584
{
15851585
ID: w1a1ID, Name: "w1a1", WorkspaceID: w1ID,
15861586
Hosts: map[dnsname.FQDN][]netip.Addr{
1587-
"w1.coder.": {ws1a1IP},
1588-
"w1a1.w1.me.coder.": {ws1a1IP},
1589-
"w1a1.w1.testy.coder.": {ws1a1IP},
1587+
"w1.mctest.": {ws1a1IP},
1588+
"w1a1.w1.me.mctest.": {ws1a1IP},
1589+
"w1a1.w1.testy.mctest.": {ws1a1IP},
15901590
},
15911591
},
15921592
{
15931593
ID: w2a1ID, Name: "w2a1", WorkspaceID: w2ID,
15941594
Hosts: map[dnsname.FQDN][]netip.Addr{
1595-
"w2a1.w2.me.coder.": {w2a1IP},
1596-
"w2a1.w2.testy.coder.": {w2a1IP},
1595+
"w2a1.w2.me.mctest.": {w2a1IP},
1596+
"w2a1.w2.testy.mctest.": {w2a1IP},
15971597
},
15981598
},
15991599
{
16001600
ID: w2a2ID, Name: "w2a2", WorkspaceID: w2ID,
16011601
Hosts: map[dnsname.FQDN][]netip.Addr{
1602-
"w2a2.w2.me.coder.": {w2a2IP},
1603-
"w2a2.w2.testy.coder.": {w2a2IP},
1602+
"w2a2.w2.me.mctest.": {w2a2IP},
1603+
"w2a2.w2.testy.mctest.": {w2a2IP},
16041604
},
16051605
},
16061606
},
@@ -1632,7 +1632,7 @@ func TestTunnelAllWorkspaceUpdatesController_DeleteAgent(t *testing.T) {
16321632
fUH := newFakeUpdateHandler(ctx, t)
16331633
fDNS := newFakeDNSSetter(ctx, t)
16341634
coordC, updateC, updateCtrl := setupConnectedAllWorkspaceUpdatesController(ctx, t, logger,
1635-
tailnet.WithDNS(fDNS, "testy"),
1635+
tailnet.WithDNS(fDNS, "testy", tailnet.DNSNameOptions{Suffix: "coder"}),
16361636
tailnet.WithHandler(fUH),
16371637
)
16381638

@@ -1775,7 +1775,7 @@ func TestTunnelAllWorkspaceUpdatesController_DNSError(t *testing.T) {
17751775
fConn := &fakeCoordinatee{}
17761776
tsc := tailnet.NewTunnelSrcCoordController(logger, fConn)
17771777
uut := tailnet.NewTunnelAllWorkspaceUpdatesController(logger, tsc,
1778-
tailnet.WithDNS(fDNS, "testy"),
1778+
tailnet.WithDNS(fDNS, "testy", tailnet.DNSNameOptions{Suffix: "coder"}),
17791779
)
17801780

17811781
updateC := newFakeWorkspaceUpdateClient(ctx, t)

vpn/client.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ func (*client) NewConn(initCtx context.Context, serverURL *url.URL, token string
107107
if err != nil {
108108
return nil, xerrors.Errorf("get connection info: %w", err)
109109
}
110+
// default to DNS suffix of "coder" if the server hasn't set it (might be too old).
111+
dnsNameOptions := tailnet.DNSNameOptions{Suffix: "coder"}
112+
if connInfo.HostnameSuffix != "" {
113+
dnsNameOptions.Suffix = connInfo.HostnameSuffix
114+
}
110115

111116
headers.Set(codersdk.SessionTokenHeader, token)
112117
dialer := workspacesdk.NewWebsocketDialer(options.Logger, rpcURL, &websocket.DialOptions{
@@ -148,7 +153,7 @@ func (*client) NewConn(initCtx context.Context, serverURL *url.URL, token string
148153
updatesCtrl := tailnet.NewTunnelAllWorkspaceUpdatesController(
149154
options.Logger,
150155
coordCtrl,
151-
tailnet.WithDNS(conn, me.Username),
156+
tailnet.WithDNS(conn, me.Username, dnsNameOptions),
152157
tailnet.WithHandler(options.UpdateHandler),
153158
)
154159
controller.WorkspaceUpdatesCtrl = updatesCtrl

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy