Skip to content

Commit 3c1cb5d

Browse files
chore: add generic DNS record for checking if Coder Connect is running (#17298)
Closes coder/internal#466 ``` $ dig -6 @fD60:627a:a42b::53 is.coder--connect--enabled--right--now.coder AAAA ; <<>> DiG 9.10.6 <<>> -6 @fD60:627a:a42b::53 is.coder--connect--enabled--right--now.coder AAAA ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62390 ;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;is.coder--connect--enabled--right--now.coder. IN AAAA ;; ANSWER SECTION: is.coder--connect--enabled--right--now.coder. 2 IN AAAA fd60:627a:a42b::53 ;; Query time: 3 msec ;; SERVER: fd60:627a:a42b::53#53(fd60:627a:a42b::53) ;; WHEN: Wed Apr 09 16:59:18 AEST 2025 ;; MSG SIZE rcvd: 134 ``` Hostname considerations: - Workspace names, usernames, and agent names can't have double hyphens, so this name can't conflict with a real Coder Connect hostname. - Components can't start or end with hyphens according to [RFC 952](https://www.rfc-editor.org/rfc/rfc952.html) - DNS records can't have hyphens in the 3rd and 4th positions, as to not conflict with IDNs https://datatracker.ietf.org/doc/html/rfc5891
1 parent e7e4753 commit 3c1cb5d

File tree

3 files changed

+30
-16
lines changed

3 files changed

+30
-16
lines changed

tailnet/conn.go

+7
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,13 @@ func NewConn(options *Options) (conn *Conn, err error) {
354354
return server, nil
355355
}
356356

357+
// A FQDN to be mapped to `tsaddr.CoderServiceIPv6`. This address can be used
358+
// when you want to know if Coder Connect is running, but are not trying to
359+
// connect to a specific known workspace.
360+
const IsCoderConnectEnabledFQDNString = "is.coder--connect--enabled--right--now.coder."
361+
362+
var IsCoderConnectEnabledFQDN, _ = dnsname.ToFQDN(IsCoderConnectEnabledFQDNString)
363+
357364
type ServicePrefix [6]byte
358365

359366
var (

tailnet/controllers.go

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"golang.org/x/xerrors"
1717
"storj.io/drpc"
1818
"storj.io/drpc/drpcerr"
19+
"tailscale.com/net/tsaddr"
1920
"tailscale.com/tailcfg"
2021
"tailscale.com/util/dnsname"
2122

@@ -1265,6 +1266,7 @@ func (t *tunnelUpdater) updateDNSNamesLocked() map[dnsname.FQDN][]netip.Addr {
12651266
}
12661267
}
12671268
}
1269+
names[IsCoderConnectEnabledFQDN] = []netip.Addr{tsaddr.CoderServiceIPv6()}
12681270
return names
12691271
}
12701272

tailnet/controllers_test.go

+21-16
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"google.golang.org/protobuf/types/known/timestamppb"
2323
"storj.io/drpc"
2424
"storj.io/drpc/drpcerr"
25+
"tailscale.com/net/tsaddr"
2526
"tailscale.com/tailcfg"
2627
"tailscale.com/types/key"
2728
"tailscale.com/util/dnsname"
@@ -1563,13 +1564,14 @@ func TestTunnelAllWorkspaceUpdatesController_Initial(t *testing.T) {
15631564

15641565
// Also triggers setting DNS hosts
15651566
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},
1567+
"w1a1.w1.me.coder.": {ws1a1IP},
1568+
"w2a1.w2.me.coder.": {w2a1IP},
1569+
"w2a2.w2.me.coder.": {w2a2IP},
1570+
"w1a1.w1.testy.coder.": {ws1a1IP},
1571+
"w2a1.w2.testy.coder.": {w2a1IP},
1572+
"w2a2.w2.testy.coder.": {w2a2IP},
1573+
"w1.coder.": {ws1a1IP},
1574+
tailnet.IsCoderConnectEnabledFQDNString: {tsaddr.CoderServiceIPv6()},
15731575
}
15741576
dnsCall := testutil.RequireRecvCtx(ctx, t, fDNS.calls)
15751577
require.Equal(t, expectedDNS, dnsCall.hosts)
@@ -1661,9 +1663,10 @@ func TestTunnelAllWorkspaceUpdatesController_DeleteAgent(t *testing.T) {
16611663

16621664
// DNS for w1a1
16631665
expectedDNS := map[dnsname.FQDN][]netip.Addr{
1664-
"w1a1.w1.testy.coder.": {ws1a1IP},
1665-
"w1a1.w1.me.coder.": {ws1a1IP},
1666-
"w1.coder.": {ws1a1IP},
1666+
"w1a1.w1.testy.coder.": {ws1a1IP},
1667+
"w1a1.w1.me.coder.": {ws1a1IP},
1668+
"w1.coder.": {ws1a1IP},
1669+
tailnet.IsCoderConnectEnabledFQDNString: {tsaddr.CoderServiceIPv6()},
16671670
}
16681671
dnsCall := testutil.RequireRecvCtx(ctx, t, fDNS.calls)
16691672
require.Equal(t, expectedDNS, dnsCall.hosts)
@@ -1716,9 +1719,10 @@ func TestTunnelAllWorkspaceUpdatesController_DeleteAgent(t *testing.T) {
17161719

17171720
// DNS contains only w1a2
17181721
expectedDNS = map[dnsname.FQDN][]netip.Addr{
1719-
"w1a2.w1.testy.coder.": {ws1a2IP},
1720-
"w1a2.w1.me.coder.": {ws1a2IP},
1721-
"w1.coder.": {ws1a2IP},
1722+
"w1a2.w1.testy.coder.": {ws1a2IP},
1723+
"w1a2.w1.me.coder.": {ws1a2IP},
1724+
"w1.coder.": {ws1a2IP},
1725+
tailnet.IsCoderConnectEnabledFQDNString: {tsaddr.CoderServiceIPv6()},
17221726
}
17231727
dnsCall = testutil.RequireRecvCtx(ctx, t, fDNS.calls)
17241728
require.Equal(t, expectedDNS, dnsCall.hosts)
@@ -1798,9 +1802,10 @@ func TestTunnelAllWorkspaceUpdatesController_DNSError(t *testing.T) {
17981802

17991803
// DNS for w1a1
18001804
expectedDNS := map[dnsname.FQDN][]netip.Addr{
1801-
"w1a1.w1.me.coder.": {ws1a1IP},
1802-
"w1a1.w1.testy.coder.": {ws1a1IP},
1803-
"w1.coder.": {ws1a1IP},
1805+
"w1a1.w1.me.coder.": {ws1a1IP},
1806+
"w1a1.w1.testy.coder.": {ws1a1IP},
1807+
"w1.coder.": {ws1a1IP},
1808+
tailnet.IsCoderConnectEnabledFQDNString: {tsaddr.CoderServiceIPv6()},
18041809
}
18051810
dnsCall := testutil.RequireRecvCtx(ctx, t, fDNS.calls)
18061811
require.Equal(t, expectedDNS, dnsCall.hosts)

0 commit comments

Comments
 (0)