我试图了解双向TLS的工作原理,我有以下示例:
我有一个想要连接到服务器“ svc1.example.com”的客户端
但服务器上有
服务器证书,其通用名称为“ svc1.example.cloud”和一个SAN 作为“ svc.example.test.cloud”。
现在,当我发出GET请求时,我得到以下信息:
x509:证书对svc.example.test.cloud有效,对svc1.example.com无效。
所以,我的问题是我应该对TLS clientConfig进行更改以包括服务器名称吗?还是应该在TLS客户端配置中添加自定义的verifyPeerCertificate函数,如下所示?
请让我知道,在verifyPeerCertificate函数中,服务器名应该是什么,我应该检查什么。
func customverify(customCName func(*x509.Certificate) bool) func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
if customCName == nil {
return nil
}
return func(_ [][]byte, verifiedChains [][]*x509.Certificate) error {
for _, certs := range verifiedChains {
leaf := certs[0]
if customCName(leaf) {
return nil
}
}
return fmt.Errorf("client identity verification failed")
}
}
func configureClient(certFile, keyFile string) (*http.Client, error) {
certpool, err := addRootCA()
if err != nil {
return nil, err
}
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, err
}
transport := ytls.NewClientTransport()
transport.TLSClientConfig.Certificates = []tls.Certificate{cert}
transport.TLSClientConfig.RootCAs = certpool
//transport.TLSClientConfig.ServerName = expectedCName
transport.TLSClientConfig.VerifyPeerCertificate = customverify(func(cert *x509.Certificate) bool {
return cert.Subject.CommonName == "svc1.example.cloud"
})
httpClient := &http.Client{Transport: transport}
return httpClient, nil
}
答案 0 :(得分:1)
由于 x509:证书对svc.example.test.cloud 有效,因此transport.TLSClientConfig.ServerName = "svc.example.test.cloud"
来自https://golang.org/pkg/crypto/tls/#Config
VerifyPeerCertificate,如果不为nil,则在常规之后调用
TLS客户端或服务器进行的证书验证。它
接收对等方提供的原始ASN.1证书,并且
正常处理发现的所有已验证链。如果返回
非零错误,握手被中止,并导致该错误。如果正常验证失败,则握手将在
之前中止。 考虑此回调。如果正常验证被
禁用 设置InsecureSkipVerify,或在ClientAuth为
时(对于服务器) RequestClientCert或RequireAnyClientCert,则此回调将
可以考虑,但是verifyChains参数始终为nil。
VerifyPeerCertificate func(rawCerts [] [] byte,verifyChains [] [] * x509.Certificate)错误
因此,如果正常验证失败,则不会调用VerifyPeerCertificate
。另外,如果通过了正常验证,我认为您不需要这张额外的支票VerifyPeerCertificate
。