go - 编写代码如何在没有 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
解决方案
推荐阅读
- html - 将 html 特殊字符定义为要在 XSD 中被 Unicode 字符替换的实体或元素
- html - 之间的区别和
- c# - PreBuildAction 使用命令输入调用 exe 时的异常
- python - 我需要重复切片我的数据框
- django - 是否可以转发已处理(在 views.py 中)的表单数据以供进一步使用?
- mainframe - OS X 上 Host On-Demand 的 PF 键
- oauth-2.0 - 将自定义字段添加到 Django Rest Framework 生成令牌
- angular - Angular 材质选项卡组主题值集
- javascript - 反应 setState 没有在第一次触发
- function - 将功能转发到新的 powershell 会话或使用调用命令?