使用不同的TLS配置进行多个HTTP客户端的操作

huangapple go评论89阅读模式
英文:

go multiple http clients with different tls configs

问题

尝试为调用多个服务的多个HTTP客户端实现不同的TLS配置(有些需要mTLS,有些不需要)。然而,我发现每个新请求都使用之前请求的TLS配置,而不是自己的TLS配置。例如,我有以下两个客户端。当client-1发起第一个请求时,它按预期验证服务器证书。但是当client-2发起下一个请求时,尽管为其配置了InsecureSkipVerify: true,它仍然尝试验证服务器证书。

client-1的配置如下:

tr := http.DefaultTransport.(*http.Transport)
tr.TLSClientConfig = &tls.Config{RootCAs: certPool, InsecureSkipVerify: false}
client1 := http.Client{Transport: tr, Timeout: timeout}

client-2的配置如下:

tr := http.DefaultTransport.(*http.Transport)
tr.TLSClientConfig = &tls.Config{RootCAs: certPool, InsecureSkipVerify: true}
client2 := http.Client{Transport: tr, Timeout: timeout}

client2请求的响应是x509: certificate signed by unknown authority。这实际上不应该发生,因为InsecureSkipVerify: true意味着不验证服务器证书。

英文:

Trying to implement multiple http clients for calling multiple services, each with their own tls configurations (some need mTLS while some do not). However, I am seeing that the each new request is using the tls config from prior request, and not its own tls config? For example, I have 2 clients as below. When client-1 makes the first request, it verifies the server cert as expected. But when client-2 makes the next request, it is still trying to verify the server cert even though InsecureSkipVerify: true is configured for it.

client-1 has config:

tr := http.DefaultTransport.(*http.Transport)
tr.TLSClientConfig = &tls.Config{RootCAs: certPool, InsecureSkipVerify: false}
client1 := http.Client{Transport: tr, Timeout: timeout}

client-2 has config:

tr := http.DefaultTransport.(*http.Transport)
tr.TLSClientConfig = &tls.Config{RootCAs: certPool, InsecureSkipVerify: true}
client2 := http.Client{Transport: tr, Timeout: timeout}

response for the client2 request is x509: certificate signed by unknown authority. This shouldn't ideally happen because InsecureSkipVerify: true means the server certs are not verified.

答案1

得分: 2

http.DefaultTransport 是在 http 包中定义的一个变量(这里),如下所示:

var DefaultTransport RoundTripper = &Transport{
	Proxy: ProxyFromEnvironment,
	DialContext: defaultTransportDialContext(&net.Dialer{
		Timeout:   30 * time.Second,
		KeepAlive: 30 * time.Second,
	}),
	ForceAttemptHTTP2:     true,
	MaxIdleConns:          100,
	IdleConnTimeout:       90 * time.Second,
	TLSHandshakeTimeout:   10 * time.Second,
	ExpectContinueTimeout: 1 * time.Second,
}

你可以使用 DefaultTransport 来创建多个 http.Client 实例,但需要记住它们都将使用相同的 Transport(即 DefaultTransport)。对 DefaultTransport 的更改将影响使用 DefaultTransport 的所有 http.Client 实例。

要解决这个问题,你可以定义自己的 Transport(可以通过复制上述代码来实现,文档中有相关说明:链接),或者在更改 TLSClientConfig 之前先复制默认的传输方式(tr := http.DefaultTransport.(*http.Transport).Clone())。

英文:

http.DefaultTransport is a variable defined in the http package (here) as:

var DefaultTransport RoundTripper = &Transport{
	Proxy: ProxyFromEnvironment,
	DialContext: defaultTransportDialContext(&net.Dialer{
		Timeout:   30 * time.Second,
		KeepAlive: 30 * time.Second,
	}),
	ForceAttemptHTTP2:     true,
	MaxIdleConns:          100,
	IdleConnTimeout:       90 * time.Second,
	TLSHandshakeTimeout:   10 * time.Second,
	ExpectContinueTimeout: 1 * time.Second,
}

You can use DefaultTransport to create multiple instances of http.Client but need to remember that they will all be using the same Transport (DefaultTransport). Changes to DefaultTransport will have an impact on all instances of http.Client that use DefaultTransport.

To resolve this either define your own Transport (perhaps by copying the above, this is covered in the docs) or make a copy (tr := http.DefaultTransport.(*http.Transport).Clone()) of the default transport before changing TLSClientConfig.

huangapple
  • 本文由 发表于 2022年8月17日 08:45:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/73381749.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定