当前位置: 首页 > 知识库问答 >
问题:

Golang的TLS连接问题

淳于功
2023-03-14

我有以下证书层次结构:

根--

整个链都明确定义了serverAuth和clientAuth作为扩展密钥用法。

在我的go代码中,我创建了一个tls。像这样配置对象:

func parseCert(certFile, keyFile string) (cert tls.Certificate, err error) {
    certPEMBlock , err := ioutil.ReadFile(certFile)
    if err != nil {
        return
    }
    var certDERBlock *pem.Block
    for {
        certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
        if certDERBlock == nil {
            break
        }
        if certDERBlock.Type == "CERTIFICATE" {
            cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
        }
    }

    // Need to flip the array because openssl gives it to us in the opposite format than golang tls expects.
    cpy := make([][]byte, len(cert.Certificate))
    copy(cpy, cert.Certificate)

    var j = 0
    for i := len(cpy)-1; i >=0; i-- {
        cert.Certificate[j] = cert.Certificate[i]
        j++
    }

    keyData, err := ioutil.ReadFile(keyFile)
    if err != nil {
        return
    }

    block, _ := pem.Decode(keyData)
    if err != nil {
        return
    }

    ecdsaKey, err := x509.ParseECPrivateKey(block.Bytes)
    if err != nil {
        return
    }

    cert.PrivateKey = ecdsaKey

    return
}

// configure and create a tls.Config instance using the provided cert, key, and ca cert files.
func configureTLS(certFile, keyFile, caCertFile string) (tlsConfig *tls.Config, err error) {

    c, err := parseCert(certFile, keyFile)
    if err != nil {
        return
    }

    ciphers := []uint16 {
        tls.TLS_RSA_WITH_AES_256_CBC_SHA,
        tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
    }

    certPool := x509.NewCertPool()
    buf, err := ioutil.ReadFile(caCertFile)
    if nil != err {
        log.Println("failed to load ca cert")
        log.Fatal(seelog.Errorf("failed to load ca cert.\n%s", err))
    }

    if !certPool.AppendCertsFromPEM(buf) {
        log.Fatalln("Failed to parse truststore")
    }


    tlsConfig = &tls.Config {
        CipherSuites: ciphers,
        ClientAuth: tls.RequireAndVerifyClientCert,
        PreferServerCipherSuites: true,
        RootCAs: certPool,
        ClientCAs: certPool,
        Certificates: []tls.Certificate{c},
    }

    return
}

certFile是证书链文件,keyFile是私钥文件。caCertFile是信任库,仅由根证书组成

所以基本上,这是我期望在我的tls里面有什么。配置来自此函数的对象:

RootCAs:仅来自caCertFile的根证书ClientCAs:同样,仅来自caCertFile的根证书,与RootCAs证书相同:一个证书链,包含certFile中的所有证书,排序为叶优先。

现在,我这里有3块。服务器、中继和客户端。客户端直接连接到中继,中继将请求转发到服务器。所有三个部分使用相同的配置代码,当然使用不同的证书/密钥。caCertFile是相同的所有3件。

现在,如果我把服务器和中继站起来,从我的浏览器连接到中继,一切都很顺利,所以我可以假设中继和服务器之间的连接是好的。当我试图将客户端连接到中继时,问题就出现了。当我这样做时,TLS握手失败并返回以下错误:

x509:由未知权限签署的证书

在中继端,我得到以下错误:http:TLS握手错误from:remoteerror:bad certificate

我在这里真的不知所措。我显然有一些设置错误,但我不确定是什么。这真的很奇怪,它从浏览器工作(这意味着配置是正确的从中继到服务器),但它不工作与相同的配置从我的客户端。

因此,如果我将unsecureskipverify:true添加到我的tls中。在中继和客户端上的Config对象上,错误更改为:

在客户端上:远程错误:错误证书

在中继上:http:TLS握手错误来自:TLS:client未提供证书

因此,客户端似乎拒绝了来自服务器(中继)的证书,因为它由于某种原因无效,因此从未将其证书发送到服务器(中继)。

我真希望go能有更好的日志记录。我甚至无法进入这个过程来了解到底发生了什么。

共有2个答案

向苗宣
2023-03-14

除了Beldin0的建议。我已经尝试了另一种方法来做到这一点。

caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(crt)

client := &http.Client{
  //some config
  Transport: &http.Transport{
    TLSClientConfig: &tls.Config{
      RootCAs: caCertPool,
    },
  },
}

这里,变量crt是您证书中的内容。
基本上,您只需将其添加到代码中(或作为配置文件读取)。
那么一切都会好的。

华凡
2023-03-14

当你说

需要翻转阵列,因为openssl以与golang tls预期相反的格式提供给我们。

我使用了openssl生成的证书,打开它们时没有问题:

tls.LoadX509KeyPair(cert, key)

无论如何,错误消息错误证书是由于服务器无法将客户端提供的证书与其根CA进行匹配。我在使用自签名证书时也遇到了这个问题,我发现唯一的解决办法是将caCertFile安装到机器系统证书中,并使用x509。SystemCertPool()而不是x509。NewCertPool()。也许其他人会有另一个解决方案?

 类似资料:
  • 我使用带有自定义KeyManager、TrustManager和客户端身份验证的java TLS服务器。连接工作并交换证书,客户端(firefox)也表示连接是加密的。我分析了与wireshark的连接,但我没有看到tls消息,wireshark只显示tcp段,而没有解码有效负载(如tls客户机hello、服务器hello,等等)。我启用调试日志,这是服务器的日志:

  • 我需要帮助,因为我对Kafka和mqtt一无所知。我正在使用docker compose创建Mosquitto broker和Kakfa之间通信的架构 我还使用confluent Kafka Connect MQTT(https://www.confluent.io/hub/confluentinc/kafka-connect-mqtt) 它对于1883端口上的通信工作得很好,但当我尝试在8883

  • 我正在研究MQTT协议。我配置了它的服务器,并使用端口1883上的Mosquito库用java进行了通信。现在,我想让这种通信更加安全。据我所知,8883端口是为其基于tls的安全通信保留的。它需要X.509证书。为此,我找到了以下教程。 http://www.embedded101.com/Blogs/PaoloPatierno/entryid/366/mqtt-over-ssl-tls-wit

  • 我们很难与远程机器(如PayPal vb)建立https连接谁从我们的系统中禁用了SSL3协议。Net应用程序。HttpWebRequest实例的GetResponse方法出现以下异常。 请求被中止:无法创建SSL/TLS安全通道。 当我们使用WireShark深入并跟踪网络日志时,我们看到远程机器返回以下错误 TLSv1。2警报(级别:致命,描述:握手失败)握手失败40 更有趣的情况是,当我尝试

  • 如何连接到FTP通过TLS在Apache蚂蚁?ftp任务似乎不支持这一点。在TLS上的FTP还有其他任务吗?

  • 有人知道我怎么才能摆脱这条信息吗?在首选项中没有ignoreCertificateErrors选项,插件也没有这样的配置?我必须在ini文件中放一些东西吗?如何设置ignoreCertificateErrors? 编辑 VonC给出的命令起作用了。但现在我又犯了一个错误: