如何在Go中配置http.Client通过Cloudflare SSL发送HTTPS请求
Go使用Cloudflare证书发起HTTPS请求时证书验证失败的解决
问题描述
我有一个基于Go语言运行的服务器,希望能通过SSL发送HTTP请求。我使用Cloudflare为域名提供的证书来实现SSL/TLS,以下是我尝试发起HTTPS请求的代码示例:
func makeHttpsRequest(w http.ResponseWriter, req *http.Request) { certs, _ := tls.LoadX509KeyPair("certificate.pem", "key.pem") rcert, _ := os.ReadFile("rootcert.pem") rpool := x509.NewCertPool() rpool.AppendCertsFromPEM(rcert) tlsConfig := &tls.Config{ Certificates: []tls.Certificate{certs}, RootCAs: rpool, } tr := &http.Transport{ TLSClientConfig: tlsConfig, } client := &http.Client{ Transport: tr } request, _ := http.NewRequest("GET", "https://example.com", nil) response, err := client.do(request) if err != nil { log.Println(err) } // code to handle the response removed from code snippet }
但调用该函数时出现错误:
tls: failed to verify certificate: x509: certificate signed by unknown authority
我确定错误源于certificate.pem、key.pem和rootcert.pem的配置问题。当前certificate.pem和key.pem是Cloudflare的Origin Certificate Authority证书及私钥,rootcert.pem是Cloudflare Origin Root CA证书。请问正确的配置应该是怎样的?
问题根源
你混淆了客户端证书和根证书信任池的作用:
- Cloudflare Origin证书(certificate.pem/key.pem)是给你的服务器接收HTTPS请求时使用的,并非客户端发起请求需要携带的证书。
- 发起HTTPS请求到外部站点时,客户端需要验证目标站点的证书是否被信任根CA签发,而非把自身的Origin证书加入客户端配置。
正确配置方案
场景1:普通HTTPS请求(访问公共站点如example.com)
直接使用Go默认的http.Client即可,它会自动调用系统内置的根CA信任池验证目标证书:
func makeHttpsRequest(w http.ResponseWriter, req *http.Request) { client := &http.Client{} request, err := http.NewRequest("GET", "https://example.com", nil) if err != nil { log.Println(err) return } response, err := client.Do(request) if err != nil { log.Println(err) return } defer response.Body.Close() // 处理响应的逻辑 }
场景2:访问使用Cloudflare Origin证书的内部站点
此时需要将Cloudflare Origin Root CA加入信任池,但不需要配置客户端证书(除非目标服务器要求双向认证):
func makeHttpsRequest(w http.ResponseWriter, req *http.Request) { // 读取Cloudflare Origin Root CA证书 rcert, err := os.ReadFile("rootcert.pem") if err != nil { log.Println(err) return } // 初始化证书池并添加根CA rpool := x509.NewCertPool() ok := rpool.AppendCertsFromPEM(rcert) if !ok { log.Println("无法将根证书添加到信任池") return } // 配置TLS,仅指定信任的根CA tlsConfig := &tls.Config{ RootCAs: rpool, // 只有当目标服务器要求客户端提供证书时,才需要设置Certificates字段 } tr := &http.Transport{ TLSClientConfig: tlsConfig, } client := &http.Client{ Transport: tr, } // 发起请求到使用Cloudflare Origin证书的站点 request, err := http.NewRequest("GET", "https://your-internal-cloudflare-site.com", nil) if err != nil { log.Println(err) return } response, err := client.Do(request) if err != nil { log.Println(err) return } defer response.Body.Close() // 处理响应的逻辑 }
关键注意事项
tls.Config.Certificates字段仅用于目标服务器要求客户端证书认证的场景,普通HTTPS请求不需要配置。- 你之前的错误是因为自定义的RootCAs只包含Cloudflare根CA,而example.com的证书由公共根CA签发,不在你的信任池内,导致验证失败。只有访问使用Cloudflare Origin证书加密的站点时,才需要用Cloudflare根CA做验证。
内容的提问来源于stack exchange,提问作者Perturbative
相关产品推荐
相关产品推荐

