了解相互TLS以及服务器名称的客户端配置

时间:2018-11-13 08:29:46

标签: ssl go tls1.2

我试图了解双向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

}

1 个答案:

答案 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