首页 > 解决方案 > 编写代码如何在没有 InsecureSkipVerify 的情况下连接自签名证书 SSL 站点?

问题描述

在一个项目中,我需要在 Go 代码中编程以连接一个使用自签名 TLS 证书部署的 https 站点;我提供了服务器证书文件:(配置了ca.cert ca.key,client.cert client.key client.csr和服务器server.cert server.key server.csr);

我发现以下代码确实有效

cert, err := tls.LoadX509KeyPair("./client.crt", "./client.key")
// if err != nil { ... }

rootCAs := x509.NewCertPool()
certs, err := ioutil.ReadFile("./ca.crt")
// if err != nil { ... }
// Append our cert to the system pool
if ok := rootCAs.AppendCertsFromPEM(certs); !ok { ... }
config := tls.Config{
    Certificates: []tls.Certificate{cert},
    InsecureSkipVerify: true,
    ServerName: "ingress.local",
    RootCAs:    rootCAs,
}
conn, err := tls.Dial("tcp", "some-site.xyz:443", &config)
if err != nil {
    if x509err, ok := err.(x509.UnknownAuthorityError); ok {
        fmt.Printf("unknown rootCert: %#v\n", x509err.Cert)
    }
    log.Fatalf("client: dial: %#v\n\t%+v", err, err)
}

tr := &http.Transport{TLSClientConfig: &config}
client := &http.Client{Transport: tr}

// Uses local self-signed cert
req, err := http.NewRequest(http.MethodGet, "https://some-site.xyz", nil)
if err != nil {
    log.Fatalf("client: http new request: %#v", err, err)
}

现在的问题是:如果我没有InsecureSkipVerify: true在 tls.Config 中设置,代码失败并出现错误: 1. 如果设置不ServerName正确,则x509.HostnameError 该服务正在使用 k8s 入口运行,我发现正确的主机名是ingress.local 2。即使我设置ServerName正确,它现在也失败了x509.UnknownAuthorityError

我尝试过的另一种方法是根本不加载ca.cert,只有一行InsecureSkipVerify: true可以使所有这些工作,并且只有必需的文件是client.cert client.key

如果我只设置InsecureSkipVerify: true而不加载客户端证书,则结果400 Bad Request No required SSL certificate was sent证明服务器端配置了需要客户端证书;

cert, err := tls.LoadX509KeyPair("./client.crt", "./client.key")
config := tls.Config{
    Certificates: []tls.Certificate{cert},
    InsecureSkipVerify: true,
}
// same tls.Dial or http.NewRequest works well ...

我想尽最大努力避免设置InsecureSkipVerify: true奇迹有没有办法让它工作没有InsecureSkipVerify: true?上面加载ca.cert到 CertPool 的方式有什么问题吗?提供的文件也包括ca.key*.csr文件,但是从所有在线现有的 TLS 连接 go 代码示例中,我看不出它们在哪里有用?

如果没有办法让它工作InsecureSkipVerify: true,那么加载它仍然有意义ca.cert吗?

再更新一件事:我已经尝试过curl --cacert ./ca.crt --cert ./client.crt --key client.key https://some-site.xyz -k与上面的 Go 代码相同,即与-k( --insecure) 一起使用,无论是否使用 cacert;但没有-k它会出现类似的错误:

* successfully set certificate verify locations:
*   CAfile: ./ca.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0

标签: gossl

解决方案


推荐阅读