¿Se puede usar OpenSSL para depurar una conexión SSL a un servidor MySQL?

21

Quiero que mi servidor web hable con el servidor de base de datos MySQL a través de una conexión SSL. El servidor web ejecuta CentOS5, el servidor de bases de datos ejecuta FreeBSD. Los certificados son proporcionados por un CA DigiCert intermedio.

MySQL debería estar usando SSL, de acuerdo con my.cnf:

# The MySQL server
[mysqld]
port            = 3306
socket          = /tmp/mysql.sock
ssl
ssl-capath = /opt/mysql/pki/CA
ssl-cert = /opt/mysql/pki/server-cert.pem
ssl-key = /opt/mysql/pki/server-key.pem

Cuando inicio MySQL, el demonio comienza sin errores. Esto sugiere que los archivos de certificado son todos legibles.

Pero cuando intento conectarme desde el servidor web al servidor de la base de datos, aparece un error:

[root@webserver ~]# mysql -h mysql.example.org -u user -p
ERROR 2026 (HY000): SSL connection error

Y si trato de depurar más con openssl:

[root@webserver ~]# openssl s_client -connect mysql.example.org:3306 0>/dev/null
CONNECTED(00000003)
15706:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:588:

¿Es esta una forma válida de probar la conexión SSL a un servidor de base de datos MySQL? El SSL23_GET_SERVER_HELLO:unknown protocolmensaje es extraño, ya que esto es lo que normalmente vería si hablara SSL en un puerto destinado a tráfico no SSL.

Este mismo comando openssl parece funcionar bien con los servidores LDAP y HTTP:

$ openssl s_client -connect ldap.example.org:636  0>/dev/null
CONNECTED(00000003)
depth=2 /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
...
$ openssl s_client -connect www.example.org:443  0>/dev/null
CONNECTED(00000003)
depth=0 /DC=org/DC=example/OU=Services/CN=www.example.org
Stefan Lasiewski
fuente
Tenga en cuenta que también puede usar Wireshark para inspeccionar el tráfico SSL a un servidor MySQL, consulte i.imgur.com/5uTkLqU.png .
Jaime Hablutzel

Respuestas:

11

OpenSSL versión 1.1.1 (lanzada el 11 de septiembre de 2018) agregó soporte para -starttls mysqlin commit a2d9cfbac5d87b03496d62079aef01c601193b58 . Lamentablemente, no puedo encontrar la referencia a esta nueva característica en el registro de cambios de OpenSSL.

Si su distribución aún no tiene esta versión, hay un binario de OpenSL compilado estáticamente en https://testssl.sh/openssl-1.0.2k-dev-chacha.pm.ipv6.Linux+FreeBSD.tar.gz que admite -starttls mysql. Encontré la referencia en http://www.danneman.org/presentations/Automating_TLS_Configuration_Verification.pdf .

Para Windows, los binarios de OpenSSL 1.1.1 se pueden encontrar en https://wiki.openssl.org/index.php/Binaries

Generé los certificados SSL como se describe en https://dev.mysql.com/doc/refman/5.7/en/creating-ssl-files-using-openssl.html , lo intenté y funciona:

$ echo | bin/openssl.Linux.x86_64.static s_client -starttls mysql -connect spx-bionic.censored.com:3306 -CAfile /tmp/ca.pem
CONNECTED(00000003)
depth=1 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = mysql test CA
verify return:1
depth=0 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = spx-bionic.censored.com
verify return:1
---
Certificate chain
 0 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=spx-bionic.censored.com
   i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=mysql test CA
 1 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=mysql test CA
   i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=mysql test CA
---
Server certificate
-----BEGIN CERTIFICATE-----
CENSORED
-----END CERTIFICATE-----
subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=spx-bionic.censored.com
issuer=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=mysql test CA
---
No client certificate CA names sent
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Shared Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Peer signing digest: SHA512
Server Temp Key: ECDH, P-521, 521 bits
---
SSL handshake has read 2599 bytes and written 632 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: AD25B7C3018E4715F262188D982AAE141A232712316E0A3292B0C14178E0F505
    Session-ID-ctx: 
    Master-Key: C121967E8FAEC4D0E0157419000660434D415251B0281CCBFC6D7A2AE8B0CC63AEFE22B332E91D31424C1BF03E5AF319
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - 82 db 03 0f c0 ce f2 26-62 bd 1b 18 71 03 88 db   .......&b...q...
    0010 - a6 66 7c 71 94 0c d5 ec-96 30 46 53 4a e6 cd 76   .f|q.....0FSJ..v
    0020 - 66 b3 22 86 7d 9f 7e 2c-14 1d 66 f2 46 8f d2 d3   f.".}.~,..f.F...
    0030 - f7 0a 0b f5 9e 05 97 e1-2b b3 ba 79 78 16 b8 59   ........+..yx..Y
    0040 - dc c5 0d a8 de 0b 3a df-4b ec f9 73 3f 4c c3 f1   ......:.K..s?L..
    0050 - 86 b6 f7 aa a7 92 84 77-9f 09 b2 cc 5d dd 35 41   .......w....].5A
    0060 - 23 5d 77 74 e1 96 91 ac-28 81 aa 83 fe fc d2 3c   #]wt....(......<
    0070 - f9 23 09 6d 00 e0 da ef-48 69 92 48 54 61 69 e8   .#.m....Hi.HTai.
    0080 - 30 0e 1f 49 7d 08 63 9e-91 70 fc 00 9f cd fe 51   0..I}.c..p.....Q
    0090 - 66 33 61 24 42 8f c2 16-57 54 48 ec 6a 87 dc 50   f3a$B...WTH.j..P

    Start Time: 1537350458
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
DONE

También hay -starttlssoporte para postgres y ldap también en OpenSSL 1.1.1. Consulte https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/apps/s_client.c#L815-L831 para ver la lista completa.

Paul Tobias
fuente
12

Respondiendo mi propia pregunta. Si tiene una mejor respuesta con buenas fuentes autorizadas, publique una respuesta.

Respuesta corta; No, OpenSSL no se puede usar para depurar conexiones SSL de MySQL. Esto se debe a que MySQL inicia la sesión usando texto sin formato y luego cambia a SSL.

Al leer https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase.html , MySQL comienza con una conexión de texto sin formato y luego se inicia el SSL real. Esto explica cómo MySQL puede escuchar en un puerto (puerto 3306) para conexiones de texto plano y encriptadas. Compare esto con un servidor HTTP o LDAP, donde se usa un puerto para conexiones de texto sin formato y un segundo puerto para conexiones cifradas.

Comienza con la conexión del cliente () al servidor que puede enviar un paquete ERR y finalizar el protocolo de enlace o enviar un paquete de protocolo de enlace inicial que el cliente responde con un paquete de respuesta de protocolo de enlace. En esta etapa, el cliente puede solicitar una conexión SSL, en cuyo caso se establece un canal de comunicación SSL antes de que el cliente envíe su respuesta de autenticación

Stefan Lasiewski
fuente
1
Esto es lo mismo que funciona SMTP cuando usa STARTTLS, y también le permite usar una conexión cifrada y no cifrada en el mismo puerto.
Synchro
Hm, supongo que el comportamiento del que estoy hablando es cómo funciona STARTTLS, de acuerdo con en.wikipedia.org/wiki/STARTTLS .
Stefan Lasiewski
2
Si bien MySQL funciona " como STARTTLS", en realidad no implementa STARTTLS, al menos de ninguna manera he descubierto que OpenSSL puede interactuar con éxito.
Christopher Schultz
1

Una causa común de este problema es que el nombre común (CN) del certificado de CA es el mismo que el del servidor y / o el certificado del cliente.

Ver aquí: https://dev.mysql.com/doc/refman/5.6/en/creating-ssl-certs.html

Intente volver a crear su CA y certificado (s) y asegúrese de utilizar un CN único en todos los casos.

Trent Lloyd
fuente
0

Me encuentro con un problema similar con el cliente MacOS X que se comunica con un servidor Ubuntu.

¿Puede verificar si la conexión funcionará si deja de lado el certificado del lado del cliente y la clave del cliente, solo teniendo la CA para el certificado del servidor? ¿Eres capaz de establecer una conexión encriptada? Esto normalmente requerirá CUALQUIER configuración para la columna ssl_type del usuario asociado.

user1204270
fuente
0

Solo quería señalar para la posteridad que si desea usar un equilibrador de carga (como un F5 o HAProxy) entre MySQL y el cliente, querrá importar su certificado SSL desde el equilibrador de carga al servidor MySQL. Esto se debe al inicio de la conexión de tipo STARTTLS.

Stephen
fuente