Me conecto a algún servidor a través de openssl:

openssl s_client -crlf -connect somehost.com:700 -cert key.pem

Y funciona. La conexión es exitosa.

Pero cuando intenté hacer lo mismo desde el código Go (ejemplo de la documentación), no me funciona:

import (
    "crypto/tls"
    "crypto/x509"
)

func main() {
    // Connecting with a custom root-certificate set.
    const rootPEM = `
-----BEGIN CERTIFICATE-----
my key text
-----END CERTIFICATE-----`

// First, create the set of root certificates. For this example we only
// have one. It's also possible to omit this in order to use the
// default root set of the current operating system.
roots := x509.NewCertPool()
ok := roots.AppendCertsFromPEM([]byte(rootPEM))
if !ok {
    panic("failed to parse root certificate")
}

conn, err := tls.Dial("tcp", "somehost.com:700", &tls.Config{
    RootCAs: roots,
})
if err != nil {
    panic("failed to connect: " + err.Error())
}
conn.Close()
}

Mi error de texto es:

panic: failed to connect: x509: certificate is valid for otherhost.com, not somehost.com [recovered]

Pregunta: ¿Qué hice mal? Y tal vez no agregué algunos parámetros tls.Config?

0
Harlam 25 ene. 2016 a las 17:41

2 respuestas

La mejor respuesta

No necesitaba verificar el certificado ssl del servidor. Era un servidor de demostración de algún registro de dominio. Entonces necesito un servidor para verificar mi certificado.

const certPEM = `-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
`
const certKey = `-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----`

cert, err := tls.X509KeyPair([]byte(certPEM), []byte(certKey))
if err != nil {
    t.Error("server: loadkeys: %s", err)
}

cfg := tls.Config{
    InsecureSkipVerify: true,
    ServerName:         "somehost.com",
    Certificates:       []tls.Certificate{cert},
}

conn, err := tls.Dial("tcp", "somehost.com:700", &cfg)
if err != nil {
    t.Error("failed to connect: " + err.Error())
}

defer conn.Close()

Entonces este código funciona en mi caso.

0
Harlam 30 ene. 2016 a las 11:25

openssl s_client es solo una herramienta de prueba que se conecta, pero no le importa mucho si el certificado es válido para la conexión. Go, en cambio, se preocupa si el certificado puede ser validado, por lo que obtiene la información de que el certificado no es válido porque el nombre no coincide.

¿qué hice mal?

Según el mensaje de error, accedió al host con el nombre de host incorrecto. O ha configurado mal su servidor para que envíe el certificado incorrecto.

2
Steffen Ullrich 25 ene. 2016 a las 14:55