设置和验证 Python MySQL 连接中使用的 SSL/TLS 版本 [英] Set and verify SSL/TLS version used in Python MySQL connection
问题描述
如何告诉 Python MySQL 连接器使用哪个 SSL/TLS 协议?特定(例如 TLS1.2)或最低要求.
如何检查已建立的连接使用的是哪种协议?
我有一个使用 mysql-connector-python
(8.0.18) 的应用程序.我连接这样的东西:
cnx = mysql.connector.connect(user='x', password='y', host='localhost', database='xyz')
通常这不会给我带来麻烦,但最近在网络托管提供商服务器上它停止工作.我现在得到的错误是:
mysql.connector.errors.InterfaceError: 2026 (HY000): SSL connection error: error:1408F10B:SSLroutines:ssl3_get_record:wrong version number
和(通过 Flask-SQLAlchemy 设置连接):
_mysql_connector.MySQLInterfaceError:SSL 连接错误:错误:140770FC:SSL 例程:SSL23_GET_SERVER_HELLO:未知协议
我可以确认的是,如果我改为执行 ssl_disabled=True
,如下所示,它可以正确连接(但我假设没有 SSL/TLS):
cnx = mysql.connector.connect(user='x', password='y', host='localhost', database='xyz', ssl_disabled=True)
我无法更改提供者服务器,但他们说如果我指定要使用的特定版本,例如 TLS1.2,那么它应该可以正确连接.他们还提到使用 ssl.OP_NO_SSLv3
标志,但是这是 SSLContext 设置的一部分,我不确定如何将其应用于我的连接.
我看到在他们的 MySQL 实例(我无法编辑)上他们没有设置值:
SHOW VARIABLES LIKE 'tls_version'
SHOW STATUS LIKE 'Ssl_cipher'
SHOW STATUS LIKE 'Ssl_version'
根据我最近的理解和来自 Andreas answer 的帮助我最终得到了以下连接:
cnx = mysql.connector.connect(user='u', password='p', host='localhost', database='db', ssl_ca='', ssl_version=ssl.PROTOCOL_TLSv1_2)
查看源代码,显然所有 kwargs
提供的也在 mysql.connector.constants.DEFAULT_CONFIGURATION
被接受.这包括文档,例如 ssl_version
和 ssl_cipher
.从 kwargs
到连接的映射似乎发生在 MySQLConnectionAbstract.connect
.请注意,设置 ssl_version
可能还需要一些其他 kwargs.我需要同时提供 ssl_ca
(可能会因 SHOW VARIABLES LIKE '%ssl%'
中的 MySQL 实例而异).
考虑到这一点,我有以下 MVCE 代码:
import mysql.connector导入 sslcnx = mysql.connector.connect(user='u', password='p', host='localhost', database='db', ssl_ca='', ssl_version=ssl.PROTOCOL_TLSv1_2)游标 = cnx.cursor()cursor.execute("选择 1")for (number,) 在光标中:打印('号码:',号码)打印('SSL 活动:',cnx._ssl_active)打印('连接SSL版本:',cnx._ssl.get(版本"))打印(套接字SSL版本:",cnx._socket.sock.ssl_version)游标.close()cnx.close()
对我来说输出:
编号:1SSL 活动:真连接 SSL 版本:_SSLMethod.PROTOCOL_TLSv1_2套接字 SSL 版本:_SSLMethod.PROTOCOL_TLSv1_2
如果我在没有指定 ssl_version
的情况下进行相同的连接,我会得到:
编号:1SSL 活动:真连接 SSL 版本:无套接字 SSL 版本:_SSLMethod.PROTOCOL_TLS
如果您将 ssl.PROTOCOL_TLSv1_2
替换为 ssl.PROTOCOL_SSLv23
,它至少应该尝试不同的协议,但如果出现问题(例如不受支持),可能会失败.>
How can I tell the Python MySQL connector which SSL/TLS protocol to use? Either specific (e.g. TLS1.2) or minimum.
How can I check which protocol is used on an established connection?
I've got an app that uses mysql-connector-python
(8.0.18). I connect something like this:
cnx = mysql.connector.connect(user='x', password='y', host='localhost', database='xyz')
Usually this gives me no trouble, but recently on a web hosting providers server it stopped working. The error I'm now getting is along the lines of:
mysql.connector.errors.InterfaceError: 2026 (HY000): SSL connection error: error:1408F10B:SSL routines:ssl3_get_record:wrong version number
And (connecting through Flask-SQLAlchemy setup):
_mysql_connector.MySQLInterfaceError: SSL connection error: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
What I can confirm is that if I instead do ssl_disabled=True
, as below, it connects properly (but without SSL/TLS I assume):
cnx = mysql.connector.connect(user='x', password='y', host='localhost', database='xyz', ssl_disabled=True)
I cannot alter the providers server, but they say that if I specify a specific version to use, for example TLS1.2, then it should connect properly. They also mention using the ssl.OP_NO_SSLv3
flag, however that is part of the SSLContext setup which I'm unsure how to apply to my connection.
I see that on their MySQL instance (which I cannot edit) they have no value set for:
SHOW VARIABLES LIKE 'tls_version'
SHOW STATUS LIKE 'Ssl_cipher'
SHOW STATUS LIKE 'Ssl_version'
From my recent understanding and help from Andreas answer I ended up with the following connect:
cnx = mysql.connector.connect(user='u', password='p', host='localhost', database='db', ssl_ca='', ssl_version=ssl.PROTOCOL_TLSv1_2)
Looking at the source, apparently all kwargs
provided that are also in mysql.connector.constants.DEFAULT_CONFIGURATION
are accepted. This includes several that are not included in the documentation, like ssl_version
and ssl_cipher
. This mapping from kwargs
to the connection appears to happen in MySQLConnectionAbstract.connect
. Note that setting ssl_version
might require some other kwargs as well. I needed to provide ssl_ca
along with it (might vary depending on what your MySQL instance has in SHOW VARIABLES LIKE '%ssl%'
).
With that in mind, I've got the following MVCE code:
import mysql.connector
import ssl
cnx = mysql.connector.connect(user='u', password='p', host='localhost', database='db', ssl_ca='', ssl_version=ssl.PROTOCOL_TLSv1_2)
cursor = cnx.cursor()
cursor.execute("SELECT 1")
for (number,) in cursor:
print('Number:', number)
print('SSL active:', cnx._ssl_active)
print('Connection SSL version:', cnx._ssl.get("version"))
print("Socket SSL version:", cnx._socket.sock.ssl_version)
cursor.close()
cnx.close()
Which for me outputs:
Number: 1
SSL active: True
Connection SSL version: _SSLMethod.PROTOCOL_TLSv1_2
Socket SSL version: _SSLMethod.PROTOCOL_TLSv1_2
If I do the same connection without specifying ssl_version
I get:
Number: 1
SSL active: True
Connection SSL version: None
Socket SSL version: _SSLMethod.PROTOCOL_TLS
If you replace ssl.PROTOCOL_TLSv1_2
with ssl.PROTOCOL_SSLv23
it should at least attempt a different protocol, but might fail if there are issues (e.g. unsupported).
这篇关于设置和验证 Python MySQL 连接中使用的 SSL/TLS 版本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!