du8980919 2018-11-13 08:29
浏览 257
已采纳

了解相互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 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.

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

报告相同问题?

悬赏问题

  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机
  • ¥20 程序进入HardFault_Handler
  • ¥15 关于#python#的问题:自动化测试