禁用通用名称验证 - 转到HTTP客户端

时间:2017-05-31 22:45:40

标签: http ssl go

如何在go http客户端内禁用通用名称验证。我正在使用通用CA进行相互TLS,因此通用名称验证无效。

tls docs说,

// 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

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

2 个答案:

答案 0 :(得分:1)

您可以使用自己的tls.Config函数传递VerifyPeerCertificate结构,然后自行检查证书。

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

  

如果正常验证失败,那么握手将在之前中止   考虑这个回调。如果禁用正常验证   设置InsecureSkipVerify然后将考虑此回调   verifiedChains参数将始终为零。

您可以查看here以获取有关如何验证证书的示例。如果你看here,你会发现即使是这个验证过程的一部分也包括检查主机名,但幸运的是,如果它被设置为skips it,你会看到它{{3}}空字符串。

所以,基本上你编写自己的VerifyPeerCertificate函数,转换rawCerts [][]byte,我认为它看起来像:

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,
}

答案 1 :(得分:0)

正常的https帖子就像这样

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)

但是如果您的网址是使用ip(例如https://127.0.0.1:8080/api/test)或者您的网址与证书通用名称不匹配,并且您只想忽略证书通用名称检查,则应该这样做

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)