dongyun7571
2017-05-31 22:45
浏览 92
已采纳

禁用通用名称验证-Go HTTP Client

How do I disable common name validation inside of a go http client. I am doing mutual TLS with a common CA and hence common name validation means nothing.

The tls docs say,

// ServerName is used to verify the hostname on the returned
// certificates unless InsecureSkipVerify is given. It is also included
// in the client's handshake to support virtual hosting unless it is
// an IP address.
ServerName string

I don't want to do InsecureSkipVerify but I don't want to validate the common name.

图片转代码服务由CSDN问答提供 功能建议

如何在go http客户端中禁用通用名称验证。 我正在使用通用CA执行双向TLS,因此通用名称验证毫无意义。

tls 文档说,

  // ServerName用于验证返回的证书上的主机名,除非InsecureSkipVerify为 给出。  
 //也包含在客户端握手中,以支持虚拟主机,除非它是一个IP地址。
 // ServerName字符串
   
 
 

不想做 InsecureSkipVerify ,但我不想验证通用名称。

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • duanjiao4763 2017-05-31 23:29
    已采纳

    You would pass a tls.Config struct with your own VerifyPeerCertificate function, and then you would check the certificate yourself.

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

    If normal verification fails then the handshake will abort before considering this callback. If normal verification is disabled by setting InsecureSkipVerify then this callback will be considered but the verifiedChains argument will always be nil.

    You can look here for an example of how to verify a certificate. Iif you look here, you'll see that part of even this verification process includes checking the hostname, but luckily you'll see that it skips it if it's set to the empty string.

    So, basically you write your own VerifyPeerCertificate function, convert the rawCerts [][]byte, which I think would look something like:

    customVerify := func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
        roots := x509.NewCertPool()
        for _, rawCert := range rawCerts {
            cert, _ := x509.ParseCertificate(rawCert)
            roots.AddCert(cert)
        }
        opts := x509.VerifyOptions{
            Roots:   roots,
        }
        _, err := cert.Verify(opts)
        return err
    }
    
    conf := tls.Config{
        //...
        VerifyPeerCertificate: customVerify,
    }
    
    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • dongxie559554 2018-02-03 03:33

    Normal https post like this

    pool := x509.NewCertPool()
    caStr, err := ioutil.ReadFile(serverCAFile)
    if err != nil {
        return nil, fmt.Errorf("read server ca file fail")
    }
    pool.AppendCertsFromPEM(caStr)
    tr := &http.Transport{
        TLSClientConfig: &tls.Config{
            RootCAs:    pool,
        },
    }
    
    client := &http.Client{Transport: tr}
    client.Post(url, bodyType, body)
    

    But if your url is use ip(ex. https://127.0.0.1:8080/api/test) or you URL is not match certificate common name, and you want to only ignore certificate common name check, should do like this

    pool := x509.NewCertPool()
    caStr, err := ioutil.ReadFile(serverCAFile)
    if err != nil {
        return nil, fmt.Errorf("read server ca file fail")
    }
    block, _ := pem.Decode(caStr)
    if block == nil {
        return nil, fmt.Errorf("Decode ca file fail")
    }
    if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
        return nil, fmt.Errorf("Decode ca block file fail")
    }
    
    cert, err := x509.ParseCertificate(block.Bytes)
    if err != nil {
        return nil, fmt.Errorf("ParseCertificate ca block file fail")
    }
    
    pool.AddCert(cert)
    
    tr := &http.Transport{
        TLSClientConfig: &tls.Config{
            RootCAs:    pool,
            ServerName: cert.Subject.CommonName,  //manual set ServerName
        },
    }
    
    client := &http.Client{Transport: tr}
    client.Post(url, bodyType, body)
    
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题