du8980919 2018-11-13 00:29
浏览 258
已采纳

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

I am trying to understand the mutual TLS working, I have the following example:

I have a client who wants to connect to server "svc1.example.com"

but the server has a

server certificate with a commonName as "svc1.example.cloud" and a SAN as "svc.example.test.cloud".

Now when I make a GET request, I get the following:

x509: certificate is valid for svc.example.test.cloud, not svc1.example.com.

So, my question is should I make a the TLS clientConfig changes to include the servername? or should I add a custom verifyPeerCertificate function in the TLS client config, something like below?

Please, let me know, what should be the Servername and what should I check for in the verifyPeerCertificate function.

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条回答 默认 最新

  • douqing0713 2018-11-13 01:09
    关注

    Since x509: certificate is valid for svc.example.test.cloud, so transport.TLSClientConfig.ServerName = "svc.example.test.cloud"

    From https://golang.org/pkg/crypto/tls/#Config

    VerifyPeerCertificate, if not nil, is called after normal
    certificate verification by either a TLS client or server. It
    receives the raw ASN.1 certificates provided by the peer and also
    any verified chains that normal processing found. If it returns a
    non-nil error, the handshake is aborted and that error results.

    If normal verification fails then the handshake will abort before
    considering this callback. If normal verification is disabled by
    setting InsecureSkipVerify, or (for a server) when ClientAuth is
    RequestClientCert or RequireAnyClientCert, then this callback will
    be considered but the verifiedChains argument will always be nil.

    VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error

    So if normal verification fails, then VerifyPeerCertificate won't get called. Also if normal verification is passed, i don't think you need this extra check VerifyPeerCertificate.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
编辑
预览

报告相同问题?

手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部