Skip to content

crypto/tls: TLS handshake timeout consistently on Windows VM LTSC2019 with private IP #74370

Open
@AnishShah

Description

@AnishShah

Go version

go version go1.24.2

Output of go env in your module/workspace:

AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/usr/local/google/home/anishshah/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/usr/local/google/home/anishshah/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build2073030948=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/usr/local/google/home/anishshah/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/usr/local/google/home/anishshah/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/lib/go-1.24'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/usr/local/google/home/anishshah/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/lib/go-1.24/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.24.2'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

The repro script was executed on GCE Windows VMs, specifically LTSC2019 and LTSC2022 versions, configured with private IP addresses only.

package main

import (
	"fmt"
	"net"
	"net/http"
	"time"
)

func DefaultHTTPTransport() *http.Transport {
	return &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		DialContext: (&net.Dialer{
			Timeout:       30 * time.Second,
			KeepAlive:     30 * time.Second,
			FallbackDelay: 300 * time.Millisecond,
		}).DialContext,
		MaxIdleConns:          10,
		IdleConnTimeout:       30 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		TLSClientConfig:       nil,
		ExpectContinueTimeout: 5 * time.Second,
	}
}

// sendHeadRequest sends a HEAD request to the given URL using the provided http.RoundTripper.
// It returns the HTTP response and an error if one occurred.
func sendHeadRequest(transport http.RoundTripper, url string) (*http.Response, error) {
	// Create an http.Client that uses the provided transport.
	client := &http.Client{
		Transport: transport,
	}

	// Create a new HEAD request.
	req, err := http.NewRequest(http.MethodHead, url, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to create HEAD request: %w", err)
	}

	// Send the request using the client.
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to send HEAD request: %w", err)
	}

	return resp, nil
}

func main() {
	fmt.Println("--- Using Default Transport ---")

	resp, err := sendHeadRequest(DefaultHTTPTransport(), "https://us-central1-artifactregistry.gcr.io/v2/gke-release-staging/gke-release-staging/csi-node-driver-registrar/manifests/sha256:1676e429022dca0bf2b54c0a18dc27e12ba01a49124ad72e86fd1a16aede024b")
	if err != nil {
		fmt.Printf("Error with default transport: %v\n", err)
	} else {
		fmt.Printf("Default Transport Status: %s\n", resp.Status)
		resp.Body.Close() // Always close the response body
	}
}

What did you see happen?

On Windows LTSC2019: The script consistently fails with TLS handshake timeout
On Windows LTSC2022: The script outputs 401 Unauthorized (expected)

What did you expect to see?

On Windows LTSC2019, I expected successful TLS handshake and output 401 Unauthoriized.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.OS-Windows

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions