如何在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
但我不想验证通用名称。
答案 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)