Golang x509:证书有效的是*.<DNS>,而不是<DB_hostname>。

huangapple go评论71阅读模式
英文:

Golang x509: Certificate is valid for *.<DNS> not <DB_hostname>

问题

我正在尝试使用Golang通过SSL连接到MySQL数据库,但是出现了以下错误信息:
>x509: 证书有效的是 *.<address1>,而不是 <DB_hostname>

我使用了这个教程创建了证书:
https://www.devdungeon.com/content/creating-self-signed-ssl-certificates-openssl

创建TLSConf的函数:

func createTLSConf() tls.Config {

    rootCertPool := x509.NewCertPool()
    pem, err := ioutil.ReadFile("certificate.pem")
    if err != nil {
        log.Fatal(err)
    }
    if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
        log.Fatal("Failed to append PEM.")
    }
    clientCert := make([]tls.Certificate, 0, 1)

    certs, err := tls.LoadX509KeyPair("certificate.pem", "privkey.pem")
    if err != nil {
        log.Fatal(err)
    }

    clientCert = append(clientCert, certs)

    return tls.Config{
        RootCAs:            rootCertPool,
        Certificates:       clientCert,
        InsecureSkipVerify: false,
    }
}

连接到数据库的代码:

    tlsConf := createTLSConf()  
    err := mysql.RegisterTLSConfig("custom", &tlsConf)

    if err != nil {
        log.Printf("Error %s when RegisterTLSConfig\n", err)
        return
    }

    dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?tls=custom", "user", "pass", "db_host", "db_name")
    db, err := sql.Open("mysql", dsn)

    if err != nil {
        log.Printf("Error %s when opening DB\n", err)
        log.Printf("%s", dsn)
        return
    }

使用数据库连接:

    defer db.Close()

    e := db.Ping()
    fmt.Println(dsn, e)

    db.Close()

输出结果:

<user>:<pass>@tcp(<db_host>)/<db_name>?tls=custom x509: 证书有效的是 *.abc-xy-pxc,而不是 <db_host>

abc-xy是db_host的一部分,abc_xy是db_name的一部分,不确定是否重要。

当将InsecureSkipVerify更改为true时,输出结果如下:

[mysql] 2022/10/21 22:31:27 packets.go:37: 远程错误: tls: 未知的证书颁发机构

有任何想法如何解决这个问题吗?

编辑:

所以,我不知道为什么,但是删除了与客户端证书相关的代码,并将InsecureSkipVerify更改为true解决了这个问题:

    func createTLSConf() tls.Config {

        rootCertPool := x509.NewCertPool()
        pem, err := ioutil.ReadFile("certificate.pem")
        if err != nil {
            log.Fatal(err)
        }
        if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
            log.Fatal("Failed to append PEM.")
        }

        return tls.Config{
            RootCAs:            rootCertPool,
            InsecureSkipVerify: true, // needed for self signed certs
        }
    }
英文:

I am trying to connect to MySQL DB using SSL via Golang and I am getting this error message
>x509: certificate is valid for *.<address1>, not <DB_hostname>

I have created certificates using this tutorial
https://www.devdungeon.com/content/creating-self-signed-ssl-certificates-openssl

Function to create TLSConf:

func createTLSConf() tls.Config {

    rootCertPool := x509.NewCertPool()
    pem, err := ioutil.ReadFile(&quot;certificate.pem&quot;)
    if err != nil {
        log.Fatal(err)
    }
    if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
        log.Fatal(&quot;Failed to append PEM.&quot;)
    }
    clientCert := make([]tls.Certificate, 0, 1)

    certs, err := tls.LoadX509KeyPair(&quot;certificate.pem&quot;, &quot;privkey.pem&quot;)
    if err != nil {
        log.Fatal(err)
    }

    clientCert = append(clientCert, certs)

    return tls.Config{
        RootCAs:            rootCertPool,
        Certificates:       clientCert,
        InsecureSkipVerify: false,
    }
}

Connection to DB

	tlsConf := createTLSConf()  
    err := mysql.RegisterTLSConfig(&quot;custom&quot;, &amp;tlsConf)

    if err != nil {
        log.Printf(&quot;Error %s when RegisterTLSConfig\n&quot;, err)
        return
    }

    dsn := fmt.Sprintf(&quot;%s:%s@tcp(%s)/%s?tls=custom&quot;, &quot;user&quot;, &quot;pass&quot;, &quot;db_host&quot;, &quot;db_name&quot;)
    db, err := sql.Open(&quot;mysql&quot;, dsn)

    if err != nil {
        log.Printf(&quot;Error %s when opening DB\n&quot;, err)
        log.Printf(&quot;%s&quot;, dsn)
        return
    }

Using connection

	defer db.Close()

    e := db.Ping()
    fmt.Println(dsn, e)

    db.Close()

Output:

&lt;user&gt;:&lt;pass&gt;@tcp(&lt;db_host&gt;)/&lt;db_name&gt;?tls=custom x509: certificate is valid for *.abc-xy-pxc, not &lt;db_host&gt;

abc-xy is a part of db_host and also abc_xy is the db_name, nut sure if it is important

When changing InsecureSkipVerify to true, the output looks like this:

[mysql] 2022/10/21 22:31:27 packets.go:37: remote error: tls: unknown certificate authority

Any idea how can I get this to work?

EDIT:

Sooo, I don't know why, but removing part of the code with Client certificates and changing InsecureSkipVerify to true solved the issue:

func createTLSConf() tls.Config {

    rootCertPool := x509.NewCertPool()
    pem, err := ioutil.ReadFile(&quot;certificate.pem&quot;)
    if err != nil {
        log.Fatal(err)
    }
    if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
        log.Fatal(&quot;Failed to append PEM.&quot;)
    }

    return tls.Config{
        RootCAs:            rootCertPool,
        InsecureSkipVerify: true, // needed for self signed certs
    }
}

答案1

得分: 1

嘿,我也是刚接触Go语言,但你可以试试这个方法。请注意,我的答案可能不是最好的,但我会尽力帮助和提问。你可以在终端中生成证书,然后使用它们。

在你的项目目录(main.go所在的位置)和Go标准库安装目录(/usr/local/go/src/crypto/tls/generate_cert.go)中,在终端中运行以下命令:

go run /usr/local/go/src/crypto/tls/generate_cert.go --rsa-bits=2048 --host=localhost

打开数据库连接,如果有错误则返回错误:

func openDB(dsn string) (*sql.DB, error){
   db, err := sql.Open("mysql",dsn)
   if err!= nil{
      return nil,err
   }
   if err = db.Ping();err!=nil{
      return nil,err
   }
   return db,nil
}

然后你需要配置服务器设置。你将拥有一个带有pem文件的http.Server。

声明一个crypto/tls.Config变量,只使用具有汇编实现的椭圆曲线。

tlsConfig := &tls.Config{
   CurvePreferences:[]tls.CurveID{tls.X25519,tls.CurveP256}
}

然后声明你的服务器。

yourServer := &http.Server{
   //你的配置
   TLSConfig : tlsConfig,
   //如果有其他配置
}

现在我们已经创建了具有特定TLS配置的服务器。你现在只需要运行你的服务器。但是,你需要使用ListenAndServeTLS方法更新你的服务器方法(第一个参数= cert,第二个参数= key)。

err = srv.ListenAndServeTLS(<cert.pem的位置>, <key.pem的位置>)
英文:

Hey I am also new to Go but you can give this a try. Consider my answer might not be the best but I am trying to be more active by helping and asking. You can generate your certificates in terminal and then use them.

run this in terminal at your project directory. (where your main.go located) and the /usr/local/go/src/crypto/tls/generate_cert.go should be the directory where Go standard library is installed.

go run /usr/local/go/src/crypto/tls/generate_cert.go --rsa-bits=2048 --host=localhost

open a DB connection return errors if any:

func openDB(dsn string) (*sql.DB, error){
   db, err := sql.Open(&quot;mysql&quot;,dsn)
   if err!= nil{
      return nil,err
   }
   if err = db.Ping();err!=nil{
      return nil,err
   }
   return db,nil
}

Then you have to configure your server settings. You will have a http.Server with your pem files.

declare a variable of crypto/tls.Config where only elliptic curves with assembly implementation are used.

tlsConfig := &amp;tls.Config{
   CurvePreferences:[]tls.CurveID{tls.X25519,tls.CurveP256}
}

then declare your server.

yourServer := &amp;http.Server{
   //Your configs
   TLSConfig : tlsConfig,
   //Your other configs if any
}

Now we have created our server with specific TLS configuration. All you have to do is running your server now. However, you have to update your server's method with ListenAndServeTLS(first arg = cert,second arg = key)

err = srv.ListenAndServeTLS(&lt;Location of your cert.pem&gt;, &lt;Location of your key.pem&gt;)

huangapple
  • 本文由 发表于 2022年10月21日 22:33:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/74155254.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定