Bug #87121 Unable to connect to a MySQL server using TLSv1.2
Submitted: 19 Jul 2017 14:42 Modified: 3 May 2018 22:25
Reporter: Paulo Jesus Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / Python Severity:S2 (Serious)
Version:2.1.5 OS:Any
Assigned to: CPU Architecture:Any

[19 Jul 2017 14:42] Paulo Jesus
Description:
A "system error: 1 [SSL: WRONG_VERSION_NUMBER] wrong version number" is issued when using connector/python to connect to a MySQL Server using TLSv1.2. Connector/python should work with any TLS version supported by the server (1, 1.1 and 1.2).

This happens using a version of OpenSSL >= 1.0.1 for Python, as required to use TLSv1.1 and TLSv1.2.
See: https://docs.python.org/2/library/ssl.html

How to repeat:
1 - Configure a MySQL server (e.g., version 5.7.18) to support SSL and use the default TLS version (1 and 1.1):

mysql> SHOW VARIABLES LIKE '%ssl%';
+--------------------+-----------------+
| Variable_name      | Value           |
+--------------------+-----------------+
| have_openssl       | YES             |
| have_ssl           | YES             |
...

mysql> SHOW VARIABLES LIKE '%tls%';
+---------------+---------------+
| Variable_name | Value         |
+---------------+---------------+
| tls_version   | TLSv1,TLSv1.1 |
+---------------+---------------+

2 - Run a simple python test script that connects to the server using SSL, the connection should succeed.
Example of the output using the script "testssl_cpy.py" (see contents below, at the end):

$ python testssl_cpy.py
os:            Linux-4.4.0-83-generic-x86_64-with-debian-stretch-sid
python         2.7.10 (default, Jul 17 2015, 17:05:23)
[GCC 4.8.4]
openssl:       OpenSSL 1.0.2g  1 Mar 2016
TLSv1.2:       5
[(u'Ssl_version', u'TLSv1')]
[(u'Ssl_cipher', u'DHE-RSA-AES256-SHA')]
[(u'tls_version', u'TLSv1,TLSv1.1')]
done 

3 - Stop the MySQL server and change the TLS version used, e.g. add "tls_version=TLSv1.1,TLSv1.2" to the configuration file "my.cnf", and restart the server.

mysql> SHOW VARIABLES LIKE '%ssl%';
+--------------------+-----------------+
| Variable_name      | Value           |
+--------------------+-----------------+
| have_openssl       | YES             |
| have_ssl           | YES             |
...

mysql> SHOW VARIABLES LIKE '%tls%';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tls_version   | TLSv1.1,TLSv1.2 |
+---------------+-----------------+

4 - Run the previous script again and notice the SSL wrong version error:

$ python testssl_cpy.py
os:            Linux-4.4.0-83-generic-x86_64-with-debian-stretch-sid
python         2.7.10 (default, Jul 17 2015, 17:05:23)
[GCC 4.8.4]
openssl:       OpenSSL 1.0.2g  1 Mar 2016
TLSv1.2:       5
Traceback (most recent call last):
  File "testssl_cpy.py", line 25, in <module>
    db_conn = mysql.connector.connect(**parameters)
  File "/home/workspace/git/test/ssl/mysql/connector/__init__.py", line 179, in connect
    return MySQLConnection(*args, **kwargs)
  File "/home/workspace/git/test/ssl/mysql/connector/connection.py", line 95, in __init__
    self.connect(**kwargs)
  File "/home/workspace/git/test/ssl/mysql/connector/abstracts.py", line 715, in connect
    self._open_connection()
  File "/home/workspace/git/test/ssl/mysql/connector/connection.py", line 210, in _open_connection
    self._ssl)
  File "/home/workspace/git/test/ssl/mysql/connector/connection.py", line 134, in _do_auth
    self._socket.switch_to_ssl(**ssl_options)
  File "/home/workspace/git/test/ssl/mysql/connector/network.py", line 427, in switch_to_ssl
    errno=2055, values=(self.get_address(), _strioerror(err)))
mysql.connector.errors.InterfaceError: 2055: Lost connection to MySQL server at 'localhost:3300', system error: 1 [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:590)

Contents of the test script:
----------------------------

$ cat testssl_cpy.py 
#!/usr/bin/env python

import os
import sys
import ssl
import socket
import platform

import mysql.connector

print("os:            " + platform.platform())
print("python         " + sys.version)
print("openssl:       " + ssl.OPENSSL_VERSION)
print("TLSv1.2:       " + str(ssl.PROTOCOL_TLSv1_2))

parameters = {
    'ssl_verify_cert': True,
    'ssl_ca': '/home/pjesus/mysql-sandboxes/3300/sandboxdata/ca.pem',
    'host': 'localhost',
    'user': 'root',
    'port': 3300
}

db_conn = mysql.connector.connect(**parameters)

cur = db_conn.cursor()
cur.execute("SHOW STATUS LIKE 'Ssl_version'")
results = cur.fetchall()
print results

cur.execute("SHOW STATUS LIKE 'Ssl_cipher'")
results = cur.fetchall()
print results

cur.execute("SHOW VARIABLES LIKE 'tls_version'")
results = cur.fetchall()
print results

cur.close()

db_conn.close()

print("done")

Suggested fix:
Allow connector/python to connect to MySQL Servers using TLSv1.2.
[19 Jul 2017 14:58] Paulo Jesus
Posted by developer:
 
Additional information:
ssl_version=ssl.PROTOCOL_TLSv1 is being used in mysql.connector.network.

The ssl_version might need to use a different value, avoid the use of a version specific SSL/TLS version (e.g., ssl.PROTOCOL_TLS for Python 2.7.13+) or use the version according to the one supported by the server.
[22 Nov 2017 14:35] Luis Delgado
We have the same problem here.

In our case we are using sqlachemy to create a connection with a MySQL database. The connection is done using the mysqlconnector and we want to use TLSv1.1.

As in the example by Paulo, if the server allows TLS1 then it works but when limitng the server to TLS1.1 we get the following error: "Lost connection to MySQL server, system error: 1 [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:748)"

Allow the connector to use the TLS defined by the server.

Thanks
[30 Jan 2018 23:15] Jesper wisborg Krogh
Posted by developer:
 
Two workarounds:

* Use the C Extension (use_pure = False)
* Change the define symbol to ssl.PROTOCOL_TLSv1_2
  From Connector/Python 2.1.7 on Oracle Linux 7:

shell$ diff lib/mysql/connector/network.py \
  /usr/lib/python2.7/site-packages/mysql/connector/network.py
420c420
<                 ssl_version=ssl.PROTOCOL_TLSv1, ciphers=cipher)
---
>                 ssl_version=ssl.PROTOCOL_TLSv1_2, ciphers=cipher)
[16 Feb 2018 10:17] Umesh Shastry
Bug #89687 marked as duplicate of this one
[16 Feb 2018 10:20] Umesh Shastry
Bug #86828 marked as duplicate of this one
[3 May 2018 22:25] Philip Olson
Posted by developer:
 
Fixed as of the upcoming MySQL Connector/Python 2.1.8 release, and here's the changelog entry:

Connecting to a MySQL server configured to use TLS versions other than
TLSv1, such as as TLSv1.1 and TLSv1.2), was not possible and failed with a
"[SSL: WRONG_VERSION_NUMBER] wrong version number" error. This is because
the connector restricted the connection to use TLSv1. 

In addition, tsl_version support was added.

Thank you for the bug report.