I want my webserver to speak to the MySQL database server over an SSL connection. The Webserver runs CentOS5, the Database Server runs FreeBSD. The certificates are provided by a intermediate CA DigiCert.
MySQL should be using ssl, according to
# 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
When I start MySQL, the daemon starts without errors. This suggests that the certificate files are all readable.
But when I try to connect from the webserver to the database server, I get an error:
[root@webserver ~]# mysql -h mysql.example.org -u user -p ERROR 2026 (HY000): SSL connection error
And if I try to debug further with 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:
Is this a valid way to test the SSL connection to a MySQL database server? The
SSL23_GET_SERVER_HELLO:unknown protocol message is strange since this typically wha you would see if you were speaking SSL on a port intended for non-SSL traffic.
This same openssl command seems to work fine with LDAP & HTTP servers:
$ 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
Update: In reading http://dev.mysql.com/doc/internals/en/ssl.html, it almost looks like MySQL starts off with a plaintext connection, and then the actual SSL is initiated afterwards. This might explain how MySQL is able to listen on one port (port 3306) for both plaintext and encrypted connections. Compare this to a HTTP or LDAP server, where one port is used for plaintext connections and a second port is used for encrypted connections.
For an unencrypted connection the server starts with its Initial Handshake Packet: ... and the client returns its Handshake Response Packet:
If client wants to do SSL and the server supports it, it would send a SSL Request Packet with the CLIENT_SSL capability enabled instead:
The rest of the communication is switch to SSL: