[英]TLS : Handshake Failure Using GoLang tls client
我正在尝试使用 golang http/tsl 客户端通过 SSL/TLS 连接到服务器,这会导致“Handshake Faliure(40)”错误,但由于某种原因,同一端点适用于 CURL 命令。 经过一番调试,我收集了以下数据。
func PrepCerts(certMap map[string]string) (*http.Transport, bool) {
ok := false
tlsConfig := &tls.Config{}
if len(certMap["ca"]) > 0 {
caCert, err := ioutil.ReadFile(certMap["ca"])
fmt.Println("caCert : ", caCert)
if err != nil {
log.Fatal(err)
} else {
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
(*tlsConfig).RootCAs = caCertPool
ok = true
}
}
if len(certMap["cert"]) > 0 && len(certMap["key"]) > 0 {
cert, err := tls.LoadX509KeyPair(certMap["cert"], certMap["key"])
fmt.Println("cert : ", cert)
if err != nil {
log.Fatal(err)
} else {
(*tlsConfig).Certificates = []tls.Certificate{cert}
ok = true
}
}
tlsConfig.BuildNameToCertificate()
return &http.Transport{TLSClientConfig: tlsConfig}, ok
}
上面使用的代码 function
client := &http.Client{
Timeout: timeout,
}
//certMap = map[string]string{
// ca : "filelocation",
// cert : "filelocation",
// key " "filelocation",
//}
if transport, ok := PrepCerts(certMap); ok {
(*client).Transport = transport
}
resp, err := client.Do(req)
从捕获的数据包可以看出,服务器正在向客户端请求证书( Certificate Request
)。 从问题中包含的详细图像还可以看出,客户端没有发送任何证书( Certificate Length
为 0 的Certificate
记录)。
还可以看出,在客户端发送(可能为空)证书后,服务器会发出警报并发出警告,因此它可能不喜欢客户端发送的内容。 因此,同意密码肯定不是问题(服务器已经同意),也不是客户端不喜欢服务器证书的问题(警报是由服务器而不是客户端发送的)。
根据您的代码,您正在尝试使用客户端证书做某事,但基于 pcap,您似乎没有成功使用一个。 所以哪里有问题。
正如FiloSottile在 Github 上所述。
我认为这里发生的是证书请求应用了您的证书不满足的约束(RSA vs ECDSA,或特定颁发者)。
使用他的建议,您可以覆盖客户端传输tls.Config.GetClientCertificate()
) 方法。
遵循此建议后,我得出的结论是 Go 不会在响应证书请求数据包时显示tls.Config.RootCAs
以及tls.Config.Certificates
。
要解决此问题,请在调用x509.LoadX509KeyPair()
之前将客户端证书及其 CA 捆绑包合并到一个文件中。 注意文件中证书的顺序很重要。 如果客户端证书不是捆绑包中的第一个证书,您将收到tls: private key does not match public key
错误。
一旦您将客户端证书与其 CA 捆绑包组合在一起,您就可以像这样将它们加载到您的客户端中。
package main
import (
"crypto/tls"
"io/ioutil"
"net/http"
"time"
log "github.com/sirupsen/logrus"
)
const (
certFile = "/location/of/client_cert.bundle.pem"
keyFile = "/location/of/client_cert.key.pem"
testURL = "https://mtls-site"
)
func main() {
clientCert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
panic(err)
}
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
Certificates: []tls.Certificate{clientCert},
},
},
}
resp, err := client.Get(testURL)
if err != nil {
panic(err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
log.Infof("%s %s", resp.Status, body)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.