From 5a5828b090f2b5641c83f3d36ee2a5577c055092 Mon Sep 17 00:00:00 2001 From: Ethan <39577870+ethanndickson@users.noreply.github.com> Date: Fri, 6 Mar 2026 01:56:54 +1100 Subject: [PATCH] fix(cli): add trailing dot to Coder Connect hostname to prevent DNS search domain expansion (#22607) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem When `coder ssh --stdio` checks for Coder Connect availability, it constructs a hostname like `agent.workspace.owner.coder` and performs a DNS AAAA lookup via `ExistsViaCoderConnect`. Without a trailing dot, this hostname is not a fully-qualified domain name (FQDN), so the system DNS resolver appends each configured search domain before querying. Go's pure-Go DNS resolver (used when `CGO_ENABLED=0`, which is the default for CLI builds) does **not** stop after getting NXDOMAIN on the first name. It tries all names in the search list sequentially: 1. `agent.workspace.owner.coder.` → NXDOMAIN (fast) 2. `agent.workspace.owner.coder.corp.example.com.` → timeout 3. `agent.workspace.owner.coder.internal.company.com.` → timeout On corporate networks where the search-domain-expanded queries hit DNS infrastructure that drops rather than responds (common for nonsensical hostnames with deep subdomain chains), each expanded query hits the full DNS timeout (default 5s × 2 attempts = 10s per name). With 2-3 search domains, this compounds to 20-30+ seconds of blocking. ## Fix Adding a trailing dot marks the hostname as an FQDN. Go's `nameList()` in `src/net/dnsclient_unix.go` returns a single-entry list for rooted names, completely bypassing search domain expansion. This is consistent with how `IsCoderConnectRunning` already handles its DNS check — `tailnet.IsCoderConnectEnabledFmtString` includes a trailing dot for exactly this reason. ## Verification Tested with a fake DNS server that responds with NXDOMAIN for `.coder` queries but drops search-domain-expanded queries: | Hostname | Time | Queries sent | |---|---|---| | `main.workstation.kevin.coder` (no trailing dot) | **~15s** | 4 (as-is + 3 search domains) | | `main.workstation.kevin.coder.` (trailing dot) | **<1ms** | 1 (FQDN only) | Closes https://github.com/coder/coder/issues/22581 _Generated by [mux](https://github.com/coder/mux) but reviewed by a human_ --- cli/ssh.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cli/ssh.go b/cli/ssh.go index 39a14e0750..2b3802b9fa 100644 --- a/cli/ssh.go +++ b/cli/ssh.go @@ -353,7 +353,11 @@ func (r *RootCmd) ssh() *serpent.Command { } coderConnectHost := fmt.Sprintf("%s.%s.%s.%s", workspaceAgent.Name, workspace.Name, workspace.OwnerName, connInfo.HostnameSuffix) - exists, _ := workspacesdk.ExistsViaCoderConnect(ctx, coderConnectHost) + // Use trailing dot to indicate FQDN and prevent DNS + // search domain expansion, which can add 20-30s of + // delay on corporate networks with search domains + // configured. + exists, _ := workspacesdk.ExistsViaCoderConnect(ctx, coderConnectHost+".") if exists { defer cancel()