diff --git a/derp/derphttp/derphttp_client.go b/derp/derphttp/derphttp_client.go index e3076ed9a..cf3be053f 100644 --- a/derp/derphttp/derphttp_client.go +++ b/derp/derphttp/derphttp_client.go @@ -24,6 +24,7 @@ import ( "sync" "time" + "golang.org/x/net/proxy" "tailscale.com/derp" "tailscale.com/net/dnscache" "tailscale.com/net/tlsdial" @@ -76,6 +77,11 @@ func NewClient(privateKey key.Private, serverURL string, logf logger.Logf) (*Cli return c, nil } +type dialer interface { + Dial(network, address string) (net.Conn, error) + DialContext(ctx context.Context, network, address string) (net.Conn, error) +} + // Connect connects or reconnects to the server, unless already connected. // It returns nil if there was already a good connection, or if one was made. func (c *Client) Connect(ctx context.Context) error { @@ -143,14 +149,21 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien host := c.url.Hostname() hostOrIP := host - var d net.Dialer + var d dialer = new(net.Dialer) + var usingProxy bool + if cd, ok := proxy.FromEnvironmentUsing(d).(dialer); ok { + usingProxy = d != cd + d = cd + } if c.DNSCache != nil { ip, err := c.DNSCache.LookupIP(ctx, host) - if err != nil { + if err == nil { + hostOrIP = ip.String() + } + if err != nil && !usingProxy { return nil, err } - hostOrIP = ip.String() } tcpConn, err = d.DialContext(ctx, "tcp", net.JoinHostPort(hostOrIP, urlPort(c.url))) diff --git a/go.mod b/go.mod index 7721be307..ba6437814 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/toqueteos/webbrowser v1.2.0 go4.org/mem v0.0.0-20200411205429-f77f31c81751 golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6 - golang.org/x/net v0.0.0-20200301022130-244492dfa37a // indirect + golang.org/x/net v0.0.0-20200301022130-244492dfa37a golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e golang.org/x/sys v0.0.0-20200501052902-10377860bb8e