2018-11-13 08:29 阅读 165


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 douqing0713 2018-11-13 09: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.

    点赞 评论 复制链接分享