From bbcc4a96287ebb87aaa47936a8f399751286cd20 Mon Sep 17 00:00:00 2001 From: Josh Vawdrey Date: Mon, 13 Mar 2023 08:51:13 +1100 Subject: [PATCH 1/4] feat: allow DERP headers to be set --- cli/root.go | 76 +++++++++++++++++++++++++++++-------- codersdk/client.go | 2 + codersdk/workspaceagents.go | 1 + go.mod | 2 +- go.sum | 4 +- tailnet/conn.go | 10 ++++- 6 files changed, 75 insertions(+), 20 deletions(-) diff --git a/cli/root.go b/cli/root.go index f3db7af279f62..c01f0b9c1a124 100644 --- a/cli/root.go +++ b/cli/root.go @@ -46,17 +46,19 @@ var ( ) const ( - varURL = "url" - varToken = "token" - varAgentToken = "agent-token" - varAgentURL = "agent-url" - varHeader = "header" - varNoOpen = "no-open" - varNoVersionCheck = "no-version-warning" - varNoFeatureWarning = "no-feature-warning" - varForceTty = "force-tty" - varVerbose = "verbose" - notLoggedInMessage = "You are not logged in. Try logging in using 'coder login '." + varURL = "url" + varToken = "token" + varAgentToken = "agent-token" + varAgentURL = "agent-url" + varHeader = "header" + varDerpHeader = "derp-header" + varDerpHeaderUseDefault = "derp-header-use-default" + varNoOpen = "no-open" + varNoVersionCheck = "no-version-warning" + varNoFeatureWarning = "no-feature-warning" + varForceTty = "force-tty" + varVerbose = "verbose" + notLoggedInMessage = "You are not logged in. Try logging in using 'coder login '." envNoVersionCheck = "CODER_NO_VERSION_WARNING" envNoFeatureWarning = "CODER_NO_FEATURE_WARNING" @@ -170,6 +172,8 @@ func Root(subcommands []*cobra.Command) *cobra.Command { _ = cmd.PersistentFlags().MarkHidden(varAgentURL) cliflag.String(cmd.PersistentFlags(), config.FlagName, "", "CODER_CONFIG_DIR", config.DefaultDir(), "Path to the global `coder` config directory.") cliflag.StringArray(cmd.PersistentFlags(), varHeader, "", "CODER_HEADER", []string{}, "HTTP headers added to all requests. Provide as \"Key=Value\"") + cliflag.StringArray(cmd.PersistentFlags(), varDerpHeader, "", "CODER_DERP_HEADER", []string{}, "HTTP headers added to all DERP requests. Provide as \"Key=Value\"") + cliflag.Bool(cmd.PersistentFlags(), varDerpHeaderUseDefault, "", "CODER_DERP_HEADER_USE_DEFAULT", false, "Use default HTTP headers for all DERP requests.") cmd.PersistentFlags().Bool(varForceTty, false, "Force the `coder` command to run as if connected to a TTY.") _ = cmd.PersistentFlags().MarkHidden(varForceTty) cmd.PersistentFlags().Bool(varNoOpen, false, "Block automatically opening URLs in the browser.") @@ -332,19 +336,61 @@ func createUnauthenticatedClient(cmd *cobra.Command, serverURL *url.URL) (*coder if err != nil { return nil, err } + + headerMap, err := parseHeaderString(headers) + if err != nil { + return nil, err + } + transport := &headerTransport{ transport: http.DefaultTransport, - headers: map[string]string{}, + headers: headerMap, } + + client.HTTPClient.Transport = transport + + derpHeaders, err := cmd.Flags().GetStringArray(varDerpHeader) + if err != nil { + return nil, err + } + + derpHeaderMap, err := parseHeaderString(derpHeaders) + if err != nil { + return nil, err + } + + client.DERPHeader = &http.Header{} + + derpHeadersUseDefault, err := cmd.Flags().GetBool(varDerpHeaderUseDefault) + if err != nil { + return nil, err + } + + if derpHeadersUseDefault { + for header, value := range headerMap { + client.DERPHeader.Set(header, value) + } + } + + for header, value := range derpHeaderMap { + client.DERPHeader.Set(header, value) + } + + return client, nil +} + +func parseHeaderString(headers []string) (map[string]string, error) { + headerMap := map[string]string{} + for _, header := range headers { parts := strings.SplitN(header, "=", 2) if len(parts) < 2 { return nil, xerrors.Errorf("split header %q had less than two parts", header) } - transport.headers[parts[0]] = parts[1] + headerMap[parts[0]] = parts[1] } - client.HTTPClient.Transport = transport - return client, nil + + return headerMap, nil } // createAgentClient returns a new client from the command context. diff --git a/codersdk/client.go b/codersdk/client.go index f21844ee4c27a..358593893e394 100644 --- a/codersdk/client.go +++ b/codersdk/client.go @@ -79,6 +79,8 @@ type Client struct { HTTPClient *http.Client URL *url.URL + DERPHeader *http.Header + // Logger is optionally provided to log requests. // Method, URL, and response code will be logged by default. Logger slog.Logger diff --git a/codersdk/workspaceagents.go b/codersdk/workspaceagents.go index 4d953f8e050d5..d4c4d1d3d32d0 100644 --- a/codersdk/workspaceagents.go +++ b/codersdk/workspaceagents.go @@ -146,6 +146,7 @@ func (c *Client) DialWorkspaceAgent(ctx context.Context, agentID uuid.UUID, opti conn, err := tailnet.NewConn(&tailnet.Options{ Addresses: []netip.Prefix{netip.PrefixFrom(ip, 128)}, DERPMap: connInfo.DERPMap, + DERPHeader: c.DERPHeader, Logger: options.Logger, BlockEndpoints: options.BlockEndpoints, }) diff --git a/go.mod b/go.mod index 31fa7acc133f0..9e287fef8fd46 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ replace github.com/tcnksm/go-httpstat => github.com/kylecarbs/go-httpstat v0.0.0 // There are a few minor changes we make to Tailscale that we're slowly upstreaming. Compare here: // https://github.com/tailscale/tailscale/compare/main...coder:tailscale:main -replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20230307022319-1e5e724a3949 +replace tailscale.com => github.com/JoshVee/tailscale v0.0.0-20230312075737-979756badabf // Switch to our fork that imports fixes from http://github.com/tailscale/ssh. // See: https://github.com/coder/coder/issues/3371 diff --git a/go.sum b/go.sum index 66da404954be1..c2a8603f17313 100644 --- a/go.sum +++ b/go.sum @@ -114,6 +114,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +github.com/JoshVee/tailscale v0.0.0-20230312075737-979756badabf h1:4r5bosAHmI1IlivX9aHZmWlrgz206xmm+iE3zBmA6l4= +github.com/JoshVee/tailscale v0.0.0-20230312075737-979756badabf/go.mod h1:jpg+77g19FpXL43U1VoIqoSg1K/Vh5CVxycGldQ8KhA= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= @@ -376,8 +378,6 @@ github.com/coder/retry v1.3.1-0.20230210155434-e90a2e1e091d h1:09JG37IgTB6n3ouX9 github.com/coder/retry v1.3.1-0.20230210155434-e90a2e1e091d/go.mod h1:r+1J5i/989wt6CUeNSuvFKKA9hHuKKPMxdzDbTuvwwk= github.com/coder/ssh v0.0.0-20220811105153-fcea99919338 h1:tN5GKFT68YLVzJoA8AHuiMNJ0qlhoD3pGN3JY9gxSko= github.com/coder/ssh v0.0.0-20220811105153-fcea99919338/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914= -github.com/coder/tailscale v1.1.1-0.20230307022319-1e5e724a3949 h1:8WfMfRTDaEpnmhCJWfFQ7JHz19GyP+EgFgLGu5ngdek= -github.com/coder/tailscale v1.1.1-0.20230307022319-1e5e724a3949/go.mod h1:jpg+77g19FpXL43U1VoIqoSg1K/Vh5CVxycGldQ8KhA= github.com/coder/terraform-provider-coder v0.6.15 h1:Llvh4RwxSQ/goy7ToTOeHf3tdEz+79qbyOh61hNnJs0= github.com/coder/terraform-provider-coder v0.6.15/go.mod h1:UIfU3bYNeSzJJvHyJ30tEKjD6Z9utloI+HUM/7n94CY= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= diff --git a/tailnet/conn.go b/tailnet/conn.go index 703e783e8f18a..aed54e6065936 100644 --- a/tailnet/conn.go +++ b/tailnet/conn.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net" + "net/http" "net/netip" "reflect" "strconv" @@ -50,8 +51,9 @@ func init() { } type Options struct { - Addresses []netip.Prefix - DERPMap *tailcfg.DERPMap + Addresses []netip.Prefix + DERPMap *tailcfg.DERPMap + DERPHeader *http.Header // BlockEndpoints specifies whether P2P endpoints are blocked. // If so, only DERPs can establish connections. @@ -160,6 +162,10 @@ func NewConn(options *Options) (conn *Conn, err error) { return nil, xerrors.New("get wireguard internals") } + if options.DERPHeader != nil { + magicConn.SetDERPHeader(options.DERPHeader.Clone()) + } + // Update the keys for the magic connection! err = magicConn.SetPrivateKey(nodePrivateKey) if err != nil { From b25a3f419c77154836bd1824b11844eaa2389802 Mon Sep 17 00:00:00 2001 From: Josh Vawdrey Date: Mon, 13 Mar 2023 11:49:40 +1100 Subject: [PATCH 2/4] chore: remove custom flag --- cli/root.go | 79 ++++++++++++++--------------------------------------- go.mod | 2 +- go.sum | 4 +-- 3 files changed, 23 insertions(+), 62 deletions(-) diff --git a/cli/root.go b/cli/root.go index c01f0b9c1a124..ff2b62b9b044e 100644 --- a/cli/root.go +++ b/cli/root.go @@ -46,19 +46,17 @@ var ( ) const ( - varURL = "url" - varToken = "token" - varAgentToken = "agent-token" - varAgentURL = "agent-url" - varHeader = "header" - varDerpHeader = "derp-header" - varDerpHeaderUseDefault = "derp-header-use-default" - varNoOpen = "no-open" - varNoVersionCheck = "no-version-warning" - varNoFeatureWarning = "no-feature-warning" - varForceTty = "force-tty" - varVerbose = "verbose" - notLoggedInMessage = "You are not logged in. Try logging in using 'coder login '." + varURL = "url" + varToken = "token" + varAgentToken = "agent-token" + varAgentURL = "agent-url" + varHeader = "header" + varNoOpen = "no-open" + varNoVersionCheck = "no-version-warning" + varNoFeatureWarning = "no-feature-warning" + varForceTty = "force-tty" + varVerbose = "verbose" + notLoggedInMessage = "You are not logged in. Try logging in using 'coder login '." envNoVersionCheck = "CODER_NO_VERSION_WARNING" envNoFeatureWarning = "CODER_NO_FEATURE_WARNING" @@ -172,8 +170,6 @@ func Root(subcommands []*cobra.Command) *cobra.Command { _ = cmd.PersistentFlags().MarkHidden(varAgentURL) cliflag.String(cmd.PersistentFlags(), config.FlagName, "", "CODER_CONFIG_DIR", config.DefaultDir(), "Path to the global `coder` config directory.") cliflag.StringArray(cmd.PersistentFlags(), varHeader, "", "CODER_HEADER", []string{}, "HTTP headers added to all requests. Provide as \"Key=Value\"") - cliflag.StringArray(cmd.PersistentFlags(), varDerpHeader, "", "CODER_DERP_HEADER", []string{}, "HTTP headers added to all DERP requests. Provide as \"Key=Value\"") - cliflag.Bool(cmd.PersistentFlags(), varDerpHeaderUseDefault, "", "CODER_DERP_HEADER_USE_DEFAULT", false, "Use default HTTP headers for all DERP requests.") cmd.PersistentFlags().Bool(varForceTty, false, "Force the `coder` command to run as if connected to a TTY.") _ = cmd.PersistentFlags().MarkHidden(varForceTty) cmd.PersistentFlags().Bool(varNoOpen, false, "Block automatically opening URLs in the browser.") @@ -336,63 +332,28 @@ func createUnauthenticatedClient(cmd *cobra.Command, serverURL *url.URL) (*coder if err != nil { return nil, err } - - headerMap, err := parseHeaderString(headers) - if err != nil { - return nil, err - } - transport := &headerTransport{ transport: http.DefaultTransport, - headers: headerMap, + headers: map[string]string{}, } - - client.HTTPClient.Transport = transport - - derpHeaders, err := cmd.Flags().GetStringArray(varDerpHeader) - if err != nil { - return nil, err - } - - derpHeaderMap, err := parseHeaderString(derpHeaders) - if err != nil { - return nil, err + for _, header := range headers { + parts := strings.SplitN(header, "=", 2) + if len(parts) < 2 { + return nil, xerrors.Errorf("split header %q had less than two parts", header) + } + transport.headers[parts[0]] = parts[1] } + client.HTTPClient.Transport = transport client.DERPHeader = &http.Header{} - derpHeadersUseDefault, err := cmd.Flags().GetBool(varDerpHeaderUseDefault) - if err != nil { - return nil, err - } - - if derpHeadersUseDefault { - for header, value := range headerMap { - client.DERPHeader.Set(header, value) - } - } - - for header, value := range derpHeaderMap { + for header, value := range transport.headers { client.DERPHeader.Set(header, value) } return client, nil } -func parseHeaderString(headers []string) (map[string]string, error) { - headerMap := map[string]string{} - - for _, header := range headers { - parts := strings.SplitN(header, "=", 2) - if len(parts) < 2 { - return nil, xerrors.Errorf("split header %q had less than two parts", header) - } - headerMap[parts[0]] = parts[1] - } - - return headerMap, nil -} - // createAgentClient returns a new client from the command context. // It works just like CreateClient, but uses the agent token and URL instead. func createAgentClient(cmd *cobra.Command) (*agentsdk.Client, error) { diff --git a/go.mod b/go.mod index 9e287fef8fd46..a9b5900a2f86c 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ replace github.com/tcnksm/go-httpstat => github.com/kylecarbs/go-httpstat v0.0.0 // There are a few minor changes we make to Tailscale that we're slowly upstreaming. Compare here: // https://github.com/tailscale/tailscale/compare/main...coder:tailscale:main -replace tailscale.com => github.com/JoshVee/tailscale v0.0.0-20230312075737-979756badabf +replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20230313001210-e2ae516db094 // Switch to our fork that imports fixes from http://github.com/tailscale/ssh. // See: https://github.com/coder/coder/issues/3371 diff --git a/go.sum b/go.sum index c2a8603f17313..ac51690528c23 100644 --- a/go.sum +++ b/go.sum @@ -114,8 +114,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/JoshVee/tailscale v0.0.0-20230312075737-979756badabf h1:4r5bosAHmI1IlivX9aHZmWlrgz206xmm+iE3zBmA6l4= -github.com/JoshVee/tailscale v0.0.0-20230312075737-979756badabf/go.mod h1:jpg+77g19FpXL43U1VoIqoSg1K/Vh5CVxycGldQ8KhA= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= @@ -378,6 +376,8 @@ github.com/coder/retry v1.3.1-0.20230210155434-e90a2e1e091d h1:09JG37IgTB6n3ouX9 github.com/coder/retry v1.3.1-0.20230210155434-e90a2e1e091d/go.mod h1:r+1J5i/989wt6CUeNSuvFKKA9hHuKKPMxdzDbTuvwwk= github.com/coder/ssh v0.0.0-20220811105153-fcea99919338 h1:tN5GKFT68YLVzJoA8AHuiMNJ0qlhoD3pGN3JY9gxSko= github.com/coder/ssh v0.0.0-20220811105153-fcea99919338/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914= +github.com/coder/tailscale v1.1.1-0.20230313001210-e2ae516db094 h1:X3+8Qw/I6c+DosStGEw5GS54UxhTGGwOgJjah1A9Lrg= +github.com/coder/tailscale v1.1.1-0.20230313001210-e2ae516db094/go.mod h1:jpg+77g19FpXL43U1VoIqoSg1K/Vh5CVxycGldQ8KhA= github.com/coder/terraform-provider-coder v0.6.15 h1:Llvh4RwxSQ/goy7ToTOeHf3tdEz+79qbyOh61hNnJs0= github.com/coder/terraform-provider-coder v0.6.15/go.mod h1:UIfU3bYNeSzJJvHyJ30tEKjD6Z9utloI+HUM/7n94CY= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= From 2e81ac62d577900b63643b70c9b977010b5fd89c Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Tue, 21 Mar 2023 17:30:20 +0000 Subject: [PATCH 3/4] Clone DERP header on client create --- cli/root.go | 1 - codersdk/workspaceagents.go | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/root.go b/cli/root.go index ff2b62b9b044e..7563b303bd20e 100644 --- a/cli/root.go +++ b/cli/root.go @@ -346,7 +346,6 @@ func createUnauthenticatedClient(cmd *cobra.Command, serverURL *url.URL) (*coder client.HTTPClient.Transport = transport client.DERPHeader = &http.Header{} - for header, value := range transport.headers { client.DERPHeader.Set(header, value) } diff --git a/codersdk/workspaceagents.go b/codersdk/workspaceagents.go index d4c4d1d3d32d0..2d4fcef3ed267 100644 --- a/codersdk/workspaceagents.go +++ b/codersdk/workspaceagents.go @@ -143,10 +143,11 @@ func (c *Client) DialWorkspaceAgent(ctx context.Context, agentID uuid.UUID, opti } ip := tailnet.IP() + header := c.DERPHeader.Clone() conn, err := tailnet.NewConn(&tailnet.Options{ Addresses: []netip.Prefix{netip.PrefixFrom(ip, 128)}, DERPMap: connInfo.DERPMap, - DERPHeader: c.DERPHeader, + DERPHeader: &header, Logger: options.Logger, BlockEndpoints: options.BlockEndpoints, }) From b543213ef8087464f0cb9757450c5088dd564632 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Tue, 21 Mar 2023 17:36:06 +0000 Subject: [PATCH 4/4] Adjust to use interface to cast headers --- cli/root.go | 22 +++++++++++----------- cli/scaletest.go | 8 ++++---- codersdk/client.go | 2 -- codersdk/workspaceagents.go | 8 +++++++- tailnet/conn.go | 1 - 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/cli/root.go b/cli/root.go index 7563b303bd20e..8d6f14b06f9a1 100644 --- a/cli/root.go +++ b/cli/root.go @@ -334,22 +334,16 @@ func createUnauthenticatedClient(cmd *cobra.Command, serverURL *url.URL) (*coder } transport := &headerTransport{ transport: http.DefaultTransport, - headers: map[string]string{}, + header: http.Header{}, } for _, header := range headers { parts := strings.SplitN(header, "=", 2) if len(parts) < 2 { return nil, xerrors.Errorf("split header %q had less than two parts", header) } - transport.headers[parts[0]] = parts[1] + transport.header.Add(parts[0], parts[1]) } - client.HTTPClient.Transport = transport - client.DERPHeader = &http.Header{} - for header, value := range transport.headers { - client.DERPHeader.Set(header, value) - } - return client, nil } @@ -661,12 +655,18 @@ func checkWarnings(cmd *cobra.Command, client *codersdk.Client) error { type headerTransport struct { transport http.RoundTripper - headers map[string]string + header http.Header +} + +func (h *headerTransport) Header() http.Header { + return h.header.Clone() } func (h *headerTransport) RoundTrip(req *http.Request) (*http.Response, error) { - for k, v := range h.headers { - req.Header.Add(k, v) + for k, v := range h.header { + for _, vv := range v { + req.Header.Add(k, vv) + } } return h.transport.RoundTrip(req) } diff --git a/cli/scaletest.go b/cli/scaletest.go index b367b580bba60..bea8c7fd17c9d 100644 --- a/cli/scaletest.go +++ b/cli/scaletest.go @@ -330,8 +330,8 @@ func scaletestCleanup() *cobra.Command { client.HTTPClient = &http.Client{ Transport: &headerTransport{ transport: http.DefaultTransport, - headers: map[string]string{ - codersdk.BypassRatelimitHeader: "true", + header: map[string][]string{ + codersdk.BypassRatelimitHeader: {"true"}, }, }, } @@ -515,8 +515,8 @@ It is recommended that all rate limits are disabled on the server before running client.HTTPClient = &http.Client{ Transport: &headerTransport{ transport: http.DefaultTransport, - headers: map[string]string{ - codersdk.BypassRatelimitHeader: "true", + header: map[string][]string{ + codersdk.BypassRatelimitHeader: {"true"}, }, }, } diff --git a/codersdk/client.go b/codersdk/client.go index 358593893e394..f21844ee4c27a 100644 --- a/codersdk/client.go +++ b/codersdk/client.go @@ -79,8 +79,6 @@ type Client struct { HTTPClient *http.Client URL *url.URL - DERPHeader *http.Header - // Logger is optionally provided to log requests. // Method, URL, and response code will be logged by default. Logger slog.Logger diff --git a/codersdk/workspaceagents.go b/codersdk/workspaceagents.go index 2d4fcef3ed267..5c52061c37ec8 100644 --- a/codersdk/workspaceagents.go +++ b/codersdk/workspaceagents.go @@ -143,7 +143,13 @@ func (c *Client) DialWorkspaceAgent(ctx context.Context, agentID uuid.UUID, opti } ip := tailnet.IP() - header := c.DERPHeader.Clone() + var header http.Header + headerTransport, ok := c.HTTPClient.Transport.(interface { + Header() http.Header + }) + if ok { + header = headerTransport.Header() + } conn, err := tailnet.NewConn(&tailnet.Options{ Addresses: []netip.Prefix{netip.PrefixFrom(ip, 128)}, DERPMap: connInfo.DERPMap, diff --git a/tailnet/conn.go b/tailnet/conn.go index c52353501501a..db259573e05dc 100644 --- a/tailnet/conn.go +++ b/tailnet/conn.go @@ -161,7 +161,6 @@ func NewConn(options *Options) (conn *Conn, err error) { if !ok { return nil, xerrors.New("get wireguard internals") } - if options.DERPHeader != nil { magicConn.SetDERPHeader(options.DERPHeader.Clone()) }