6.3.2 加密的连接 TLS 协议和密码

MySQL 支持多种 TLS 协议和密码,并允许配置允许加密连接的协议和密码。还可以确定当前会话使用哪种协议和密码。

支持的连接 TLS 协议

MySQL 支持使用 TLSv1,TLSv1.1 和 TLSv1.2 协议的加密连接,从低到高的 Sequences 列出。实际允许连接的协议集受多种因素影响:

  • MySQL 配置。可以在服务器端和 Client 端上都配置允许的 TLS 协议,以仅包括支持的 TLS 协议的子集。双方的配置必须至少包含一个共同的协议,否则连接尝试无法协商要使用的协议。有关详细信息,请参见连接 TLS 协议协商

  • 系统范围的主机配置。主机系统可能只允许某些 TLS 协议,这意味着即使 MySQL 本身允许它们,MySQL 连接也不能使用不允许的协议:

  • 假设 MySQL 配置允许 TLSv1,TLSv1.1 和 TLSv1.2,但是您的主机系统配置仅允许使用 TLSv1.2 或更高版本的连接。在这种情况下,即使将 MySQL 配置为允许使用 TLSv1 或 TLSv1.1 的 MySQL 连接,也无法构建,因为主机系统不允许它们。

    • 如果 MySQL 配置允许 TLSv1,TLSv1.1 和 TLSv1.2,但是您的主机系统配置仅允许使用 TLSv1.3 或更高版本的连接,则您将无法构建 MySQL 连接,因为主机不允许 MySQL 允许的协议系统。

此问题的解决方法包括:

  • 更改系统范围的主机配置,以允许其他 TLS 协议。请查阅 os 文档以获取指示。例如,您的系统可能有一个/etc/ssl/openssl.cnf文件,其中包含以下行以将 TLS 协议限制为 TLSv1.2 或更高版本:
[system_default_sect]
MinProtocol = TLSv1.2

将值更改为较低的协议版本或None将使系统更具宽松性。这种解决方法的缺点是,允许较低(较不安全)的协议可能会带来不利的安全后果。

  • 如果您不能或不想更改主机系统 TLS 配置,请更改 MySQL 应用程序以使用主机系统允许的更高(更安全)的 TLS 协议。对于仅支持较低协议版本的 MySQL 的较早版本可能无法实现。例如,TLSv1 是 MySQL 5.6.46 之前唯一受支持的协议,因此,即使 Client 端来自支持更高协议版本的较新 MySQL 版本,尝试连接到 5.6.46 之前的服务器的尝试也会失败。在这种情况下,可能需要升级到支持其他 TLS 版本的 MySQL 版本。

  • SSL 库。如果 SSL 库不支持特定协议,则 MySQL 和以下讨论中指定该协议的任何部分均不适用。

  • 使用 OpenSSL 1.0.1 或更高版本进行编译时,MySQL 支持 TLSv1,TLSv1.1 和 TLSv1.2 协议。

    • 使用 yaSSL 进行编译时,MySQL 支持 TLSv1 和 TLSv1.1 协议。

Note

仅在 MySQL 5.7.28 之前,才可以使用 yaSSL 替代 OpenSSL 来编译 MySQL。从 MySQL 5.7.28 开始,对 yaSSL 的支持已删除,所有 MySQL 构建都使用 OpenSSL。

连接 TLS 协议配置

在服务器端,tls_version系统变量的值确定 MySQL 服务器允许进行加密连接的 TLS 协议。 tls_version值适用于使用常规主/从复制从 Client 端和从服务器进行的连接。变量值是此列 table 中一个或多个逗号分隔的协议版本的列 table(不区分大小写):TLSv1,TLSv1.1,TLSv1.2. 默认情况下,此变量列出用于编译 MySQL 的 SSL 库支持的所有协议(对于 OpenSSL,TLSv1,TLSv1.1,TLSv1.2,对于 yaSSL,TLSv1,TLSv1.1)。要在运行时确定tls_version的值,请使用以下语句:

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

要更改tls_version的值,请在服务器启动时进行设置。例如,要允许使用 TLSv1.1 或 TLSv1.2 协议的连接,但禁止使用安全性较低的 TLSv1 协议的连接,请在服务器my.cnf文件中使用以下这些行:

[mysqld]
tls_version=TLSv1.1,TLSv1.2

为了更加严格并且仅允许 TLSv1.2 连接,请像这样设置tls_version(假设您的服务器是使用 OpenSSL 编译的,因为 yaSSL 不支持 TLSv1.2):

[mysqld]
tls_version=TLSv1.2

在 Client 端,--tls-version选项指定 Client 端程序允许连接到服务器的 TLS 协议。选项值的格式与前面介绍的tls_version系统变量的格式相同(一个或多个逗号分隔的协议版本的列 table)。

对于主/从复制,更改为主语句的MASTER_TLS_VERSION选项指定从属服务器允许与主服务器连接的 TLS 协议。选项值的格式与前面介绍的tls_version系统变量的格式相同。参见第 16.3.8 节“设置复制以使用加密的连接”

可以为MASTER_TLS_VERSION指定的协议取决于 SSL 库。此选项独立于服务器tls_version的值,不受其影响。例如,可以将充当复制从属的服务器配置为tls_version设置为 TLSv1.2,以仅允许使用 TLSv1.2 的传入连接,也可以将MASTER_TLS_VERSION配置为 TLSv1.1,以仅允许 TLSv1.1 进行传出从机连接到主机。

TLS 协议配置会影响给定连接使用哪种协议,如连接 TLS 协议协商中所述。

应该选择允许的协议,以免在列 table 中留下“漏洞”。例如,这些服务器配置值没有漏洞:

tls_version=TLSv1,TLSv1.1,TLSv1.2
tls_version=TLSv1.1,TLSv1.2
tls_version=TLSv1.2

该值确实有孔,不应使用:

tls_version=TLSv1,TLSv1.2       (TLSv1.1 is missing)

对空洞的禁止也适用于其他配置上下文,例如对于 Client 端或复制从属。

允许的协议列 table 不应为空。如果将 TLS 版本参数设置为空字符串,则无法构建加密连接:

  • tls_version:服务器不允许加密的传入连接。

  • --tls-version:Client 端不允许到服务器的加密传出连接。

  • MASTER_TLS_VERSION:复制从属服务器不允许与主服务器进行加密的传出连接。

连接密码配置

一组默认密码适用于加密连接,可以通过显式配置允许的密码来覆盖这些密码。在构建连接的过程中,连接的两端必须允许使用某些共同的密码,否则连接将失败。在双方通用的允许密码中,SSL 库选择所提供证书支持的具有最高优先级的密码。

要为加密连接指定一个或多个密码,请在服务器端设置ssl_cipher系统变量,并为 Client 端程序使用--ssl-cipher选项。

对于以该服务器实例为主服务器的主/从复制连接,请设置ssl_cipher系统变量。如果此服务器实例是从服务器,则对_语句使用MASTER_SSL_CIPHER选项。参见第 16.3.8 节“设置复制以使用加密的连接”

给定的密码只能与特定的 TLS 协议一起使用,这会影响 TLS 协议的协商过程。参见连接 TLS 协议协商

要确定给定服务器支持的密码,请检查Ssl_cipher_list status 变量的会话值:

SHOW SESSION STATUS LIKE 'Ssl_cipher_list';

Ssl_cipher_list状态变量列出了可能的 SSL 密码(对于非 SSL 连接,为空)。可用密码的集合取决于您的 MySQL 版本以及 MySQL 是使用 OpenSSL 还是 yaSSL 编译的,以及(对于 OpenSSL)库版本(用于编译 MySQL)。

MySQL 将默认的密码列 table 传递给 SSL 库。

MySQL 将此默认密码列 table 传递给 OpenSSL:

ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-AES128-SHA256
ECDHE-RSA-AES128-SHA256
ECDHE-ECDSA-AES256-SHA384
ECDHE-RSA-AES256-SHA384
DHE-RSA-AES128-GCM-SHA256
DHE-DSS-AES128-GCM-SHA256
DHE-RSA-AES128-SHA256
DHE-DSS-AES128-SHA256
DHE-DSS-AES256-GCM-SHA384
DHE-RSA-AES256-SHA256
DHE-DSS-AES256-SHA256
ECDHE-RSA-AES128-SHA
ECDHE-ECDSA-AES128-SHA
ECDHE-RSA-AES256-SHA
ECDHE-ECDSA-AES256-SHA
DHE-DSS-AES128-SHA
DHE-RSA-AES128-SHA
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
DHE-RSA-AES256-SHA
AES128-GCM-SHA256
DH-DSS-AES128-GCM-SHA256
ECDH-ECDSA-AES128-GCM-SHA256
AES256-GCM-SHA384
DH-DSS-AES256-GCM-SHA384
ECDH-ECDSA-AES256-GCM-SHA384
AES128-SHA256
DH-DSS-AES128-SHA256
ECDH-ECDSA-AES128-SHA256
AES256-SHA256
DH-DSS-AES256-SHA256
ECDH-ECDSA-AES256-SHA384
AES128-SHA
DH-DSS-AES128-SHA
ECDH-ECDSA-AES128-SHA
AES256-SHA
DH-DSS-AES256-SHA
ECDH-ECDSA-AES256-SHA
DHE-RSA-AES256-GCM-SHA384
DH-RSA-AES128-GCM-SHA256
ECDH-RSA-AES128-GCM-SHA256
DH-RSA-AES256-GCM-SHA384
ECDH-RSA-AES256-GCM-SHA384
DH-RSA-AES128-SHA256
ECDH-RSA-AES128-SHA256
DH-RSA-AES256-SHA256
ECDH-RSA-AES256-SHA384
ECDHE-RSA-AES128-SHA
ECDHE-ECDSA-AES128-SHA
ECDHE-RSA-AES256-SHA
ECDHE-ECDSA-AES256-SHA
DHE-DSS-AES128-SHA
DHE-RSA-AES128-SHA
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
DHE-RSA-AES256-SHA
AES128-SHA
DH-DSS-AES128-SHA
ECDH-ECDSA-AES128-SHA
AES256-SHA
DH-DSS-AES256-SHA
ECDH-ECDSA-AES256-SHA
DH-RSA-AES128-SHA
ECDH-RSA-AES128-SHA
DH-RSA-AES256-SHA
ECDH-RSA-AES256-SHA
DES-CBC3-SHA

MySQL 将此默认密码列 table 传递给 yaSSL:

DHE-RSA-AES256-SHA
DHE-RSA-AES128-SHA
AES128-RMD
DES-CBC3-RMD
DHE-RSA-AES256-RMD
DHE-RSA-AES128-RMD
DHE-RSA-DES-CBC3-RMD
AES256-SHA
RC4-SHA
RC4-MD5
DES-CBC3-SHA
DES-CBC-SHA
EDH-RSA-DES-CBC3-SHA
EDH-RSA-DES-CBC-SHA
AES128-SHA:AES256-RMD

从 MySQL 5.7.10 开始,这些密码限制已经到位:

  • 以下密码受到永久限制:
!DHE-DSS-DES-CBC3-SHA
!DHE-RSA-DES-CBC3-SHA
!ECDH-RSA-DES-CBC3-SHA
!ECDH-ECDSA-DES-CBC3-SHA
!ECDHE-RSA-DES-CBC3-SHA
!ECDHE-ECDSA-DES-CBC3-SHA
  • 下列类别的密码受到永久限制:
!aNULL
!eNULL
!EXPORT
!LOW
!MD5
!DES
!RC2
!RC4
!PSK
!SSLv3

如果服务器是使用设置为使用前面任何受限密码或密码类别的证书的ssl_cert系统变量启动的,则服务器将禁用对加密连接的支持。

连接 TLS 协议协商

MySQL 中的连接尝试协商使用双方均可使用的最高 TLS 协议版本,并且双方均可使用协议兼容的加密密码。协商过程取决于多种因素,例如用于编译服务器和 Client 端的 SSL 库,TLS 协议和加密密码配置以及所使用的密钥大小:

  • 为了成功进行连接,服务器和 Client 端 TLS 协议配置必须允许某些通用协议。

  • 类似地,服务器和 Client 端加密密码配置必须允许一些共同的密码。给定的密码只能与特定的 TLS 协议一起使用,因此除非存在兼容的密码,否则不会选择可用于协商过程的协议。

  • 如果服务器和 Client 端是使用 OpenSSL 编译的,则尽可能使用 TLSv1.2. 如果服务器和 Client 端之一或两者都使用 yaSSL 编译,则在可能的情况下使用 TLSv1.1. (“可能”table 示服务器和 Client 端配置都必须允许所指示的协议,并且都必须还允许某些协议兼容的加密密码.)否则,MySQLcontinue 浏览可用协议列 table,从安全性更高的协议到安全性较低的协议。协商 Sequences 与配置协议的 Sequences 无关。例如,无论tls_version的值为TLSv1,TLSv1.1,TLSv1.2还是TLSv1.2,TLSv1.1,TLSv1,协商 Sequences 都相同。

Note

在 MySQL 5.7.10 之前,MySQL 对于 OpenSSL 和 yaSSL 仅支持 TLSv1,并且不存在用于指定允许使用哪些 TLS 协议的系统变量或 Client 端选项。

  • TLSv1.2 不适用于密钥大小为 512 位或更小的所有密码。要将此协议与这样的密钥一起使用,请在服务器端设置ssl_cipher系统变量,或使用--ssl-cipherClient 端选项显式指定密码名称:
AES128-SHA
AES128-SHA256
AES256-SHA
AES256-SHA256
CAMELLIA128-SHA
CAMELLIA256-SHA
DES-CBC3-SHA
DHE-RSA-AES256-SHA
RC4-MD5
RC4-SHA
SEED-SHA
  • 为了提高安全性,请使用 RSA 密钥大小至少为 2048 位的证书。

如果服务器和 Client 端没有共同的允许协议,并且没有共同的协议兼容密码,则服务器将终止连接请求。例子:

  • 如果服务器配置了tls_version=TLSv1.1,TLSv1.2

  • 对于使用--tls-version=TLSv1调用的 Client 端以及仅支持 TLSv1 的较旧 Client 端,连接尝试将失败。

    • 同样,对于配置为MASTER_TLS_VERSION = 'TLSv1'的复制从属服务器以及仅支持 TLSv1 的较旧的从属服务器,连接尝试将失败。
  • 如果服务器配置为tls_version=TLSv1或为仅支持 TLSv1 的较旧服务器:

  • 对于使用--tls-version=TLSv1.1,TLSv1.2调用的 Client 端,连接尝试失败。

    • 同样,配置为MASTER_TLS_VERSION = 'TLSv1.1,TLSv1.2'的复制从属服务器的连接尝试失败。

MySQL 允许指定要支持的协议列 table。该列 table 直接向下传递到基础 SSL 库,最终由该库决定,它实际上从提供的列 table 中启用了哪些协议。请参阅 MySQL 源代码和 OpenSSL SSL_CTX_new()文档,以获取有关 SSL 库如何处理此信息的信息。

监视当前 Client 端会话 TLS 协议和密码

要确定当前 Client 端会话使用哪种加密 TLS 协议和密码,请检查Ssl_versionSsl_cipher状态变量的会话值:

mysql> SELECT * FROM performance_schema.session_status
       WHERE VARIABLE_NAME IN ('Ssl_version','Ssl_cipher');
+---------------+---------------------------+
| VARIABLE_NAME | VARIABLE_VALUE            |
+---------------+---------------------------+
| Ssl_cipher    | DHE-RSA-AES128-GCM-SHA256 |
| Ssl_version   | TLSv1.2                   |
+---------------+---------------------------+

如果连接未加密,则两个变量都为空。