为了账号安全,请及时绑定邮箱和手机立即绑定

使用自签名证书的 TLS 连接失败

使用自签名证书的 TLS 连接失败

Go
三国纷争 2022-01-10 10:58:00
当使用我自己的“开发人员”证书在我的笔记本电脑上本地运行以访问内部服务时,以下简化的测试用例代码可以工作如果我在具有动态生成的证书(所有这些都由我组织中的一个单独的团队处理)的远程计算机上运行,它会失败并显示 400 和“未发送所需的 SSL 证书”错误但是,如果我在远程机器上使用 curl,并指定与我的 Go 代码中引用的相同的证书,它将起作用所以似乎证书不是问题,而是 Go 代码,但这本身似乎不是问题,因为它在本地与我自己的证书一起使用package mainimport (  "crypto/tls"  "crypto/x509"  "fmt"  "io/ioutil"  "net/http"  "os"  "time")func main() {  transport, transErr := configureTLS()  if transErr != nil {    fmt.Printf("trans error: %s", transErr.Error())    return  }  timeout := time.Duration(1 * time.Second)  client := http.Client{    Transport: transport,    Timeout:   timeout,  }  resp, clientErr := client.Get("https://my-service-with-nginx/")  if clientErr != nil {    fmt.Printf("client error: %s", clientErr.Error())  } else {    defer resp.Body.Close()    contents, contErr := ioutil.ReadAll(resp.Body)    if contErr != nil {      fmt.Printf("contents error: %s", contErr.Error())    }    fmt.Printf("\n\ncontents:\n\n%+v", string(contents))  }}func configureTLS() (*http.Transport, error) {  certPath := "/path/to/client.crt"  keyPath := "/path/to/client.key"  caPath := "/path/to/ca.crt"  // Load client cert  cert, err := tls.LoadX509KeyPair(certPath, keyPath)  if err != nil {    return nil, err  }  // Load CA cert  caCert, err := ioutil.ReadFile(caPath)  if err != nil {    return nil, err  }  caCertPool := x509.NewCertPool()  caCertPool.AppendCertsFromPEM(caCert)  // Setup HTTPS client  tlsConfig := &tls.Config{    Certificates:       []tls.Certificate{cert},    RootCAs:            caCertPool,    InsecureSkipVerify: true,  }  tlsConfig.BuildNameToCertificate()  return &http.Transport{TLSClientConfig: tlsConfig}, nil}有谁知道为什么会发生这种情况?我认为这可能是 Go 的重新协商错误(从 1.6 开始),但我认为情况并非如此,否则在本地运行应用程序时它会失败(但它不会,使用我自己的开发证书并且在本地运行正常 - 只有在具有不同证书的远程实例上运行时才会出现问题;并且这些证书不是问题,因为它们在使用时工作正常curl)
查看完整描述

1 回答

?
偶然的你

TA贡献1841条经验 获得超3个赞

所以这里的实际问题部分与我的组织基础设施有关,部分与 nginx 的使用方式有关ssl_client_certificate

我们有 int、test 和 live 环境

我被引导相信环境可以相互交流。

所以我在 int 上设置了我的服务,并且我能够从那里使用 curl 与实时环境中的另一个服务设置进行通信。

使用 Go 跨环境通信时出现问题。

对我来说,快速的解决方案是确保当我对其他服务进行 GET 时,而不是使用:

https://service.live.me.com

我会使用:

https://service.int.me.com

或者:

https://service.test.me.com

根据我的代码运行的环境。

显然,对于有类似问题但没有相同设置的其他人来说,这不是解决方案。


所以对于那些仍然需要解决方案的人......


我还将尝试(并且显然为这个人工作)是让我试图与之通信的服务来修改他们的 nginx conf,以便他们设置ssl_client_certificate不只是指向客户端证书,而是指向组合证书(包括整个 CA 链)。

这是因为显然 Go 不会在其响应中发回任何证书,除非服务器已通过 CA 及其响应。

我最初怀疑这是 Go 1.6 及更低版本中的经典重新协商错误,但在这种情况下并非如此。

希望这可以帮助同一条船上的其他人。


查看完整回答
反对 回复 2022-01-10
  • 1 回答
  • 0 关注
  • 293 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信