8.3.1 配置 MySQL 使用加密连接
有多个配置参数可用于指示是否使用加密连接,并指定适当的证书和密钥文件。这部分提供了关于配置服务器和客户端以使用加密连接的总体指导:
加密连接也可以在其他上下文中使用,如以下部分所述:
-
在源服务器和副本服务器之间的复制。见第19.3.1节,“使用加密连接设置复制”。
-
在 Group Replication 服务器之间。见第20.6.2节,“使用 Secure Socket Layer (SSL) 安全 Group Communication”。
-
基于 MySQL C API 的客户端程序。见支持加密连接。
创建证书和密钥文件的指南可在第8.3.3节,“创建 SSL 和 RSA 证书和密钥”中找到。
要强制客户端使用加密连接,启用require_secure_transport
系统变量。见加密连接强制执行。
这些系统变量在服务器端指定了服务器使用的证书和密钥文件,以允许客户端建立加密连接:
-
ssl_ca
:证书授权机构 (CA) 证书文件的路径名。(ssl_capath
类似,但指定证书文件目录的路径名。) -
ssl_cert
: 服务器公共密钥证书文件的路径名。这份证书可以发送给客户端,并对其与CA证书进行身份验证。 -
ssl_key
: 服务器私钥文件的路径名。
例如,要启用加密连接,启动服务器时在my.cnf
文件中添加以下行,根据需要更改文件名:
[mysqld]
ssl_ca=ca.pem
ssl_cert=server-cert.pem
ssl_key=server-key.pem
另外,如果要要求客户端使用加密连接,启用require_secure_transport
系统变量:
[mysqld]
ssl_ca=ca.pem
ssl_cert=server-cert.pem
ssl_key=server-key.pem
require_secure_transport=ON
每个证书和密钥系统变量都指向PEM格式的文件。如果需要创建所需的证书和密钥文件,请见第8.3.3节,“创建SSL和RSA证书和密钥”。使用OpenSSL编译的MySQL服务器可以在启动时自动生成缺少的证书和密钥文件。见第8.3.3.1节,“使用MySQL创建SSL和RSA证书和密钥”。Alternatively,如果您有MySQL源代码,您可以使用示例证书和密钥文件在其
mysql-test/std_data
目录中测试您的设置。
服务器执行证书和密钥文件自动发现。如果没有明确的加密连接选项来配置加密连接,服务器将尝试在启动时自动启用加密连接支持:
-
如果服务器发现名为
ca.pem
、server-cert.pem
和server-key.pem
的有效证书和密钥文件在数据目录中,它将启用客户端支持加密连接。(文件不需要自动生成;重要的是它们有这些名称并且是有效的。) -
如果服务器找不到有效证书和密钥文件在数据目录中,它将继续执行,但没有支持客户端加密连接。
如果服务器自动启用加密连接支持,它将在错误日志中写一条注释。如果服务器发现CA证书是自签名的,它将在错误日志中写一条警告。(证书是自签名的,如果由服务器自动生成。)
MySQL还提供了以下系统变量来控制服务器端加密连接:
-
ssl_cipher
: 加密连接加密算法的列表。 -
ssl_crl
: 加密连接证书撤销列表文件的路径名。(ssl_crlpath
类似,但指定证书撤销列表文件目录的路径名。) -
tls_version
,tls_ciphersuites
: 服务器允许加密连接使用的加密协议和cipher套件;见第8.3.2节,“加密连接TLS协议和cipher”。例如,您可以将tls_version
设置为防止客户端使用不安全的协议。
如果服务器无法从系统变量中创建有效的TLS上下文,以便控制服务器端加密连接,则服务器将不支持加密连接。
系统变量tls_
和xxx
ssl_
可以在运行时更改,不仅在启动时更改。如果使用xxx
SET GLOBAL
更改,新的值仅在服务器重启后生效。如果使用SET PERSIST
更改,新的值将在服务器重启后继续生效。见第15.7.6.1节,“SET Syntax for Variable Assignment”。然而,运行时对这些变量的更改不会立即影响新的连接的TLS上下文,因为后续部分将解释。
与启用运行时更改TLS上下文相关的系统变量的同时,服务器还启用了对实际TLS上下文的运行时更新。这可能是有用的示例,以避免在SSL证书过期后重启MySQL服务器。
为了创建初始TLS上下文,服务器使用了启动时系统变量的值。为了暴露上下文值,服务器还初始化了相应的状态变量。以下表格显示了定义TLS上下文的系统变量和暴露当前活动上下文值的状态变量。
表8.12 系统变量和状态变量:服务器主连接界面TLS上下文
System Variable Name | Corresponding Status Variable Name |
---|---|
ssl_ca |
Current_tls_ca |
ssl_capath |
Current_tls_capath |
ssl_cert |
Current_tls_cert |
ssl_cipher |
当前_tls_cipher |
ssl_crl |
当前_tls_crl |
ssl_crlpath |
当前_tls_crlpath |
ssl_key |
当前_tls_key |
tls_ciphersuites |
当前_tls_ciphersuites |
tls_version |
当前_tls_version |
这些活动TLS上下文值也会在性能Schematls_channel_status
表中公开为属性,包括其他活动TLS上下文的属性。
要在运行时重新配置TLS上下文,请执行以下步骤:
-
将每个TLS上下文相关的系统变量设置为其新值。
-
执行
ALTER INSTANCE RELOAD TLS
语句。这句语句重新配置活动TLS上下文,以当前TLS上下文相关系统变量的值为准。它还将上下文相关的状态变量设置为反映新的活动上下文值。语句需要CONNECTION_ADMIN
特权。 -
新建立的连接在执行
ALTER INSTANCE RELOAD TLS
语句后使用新的TLS上下文。现有连接保持不变。如果需要终止现有连接,请使用KILL
语句。
每对系统变量和状态变量的成员可能在重新配置过程中有不同的值:
-
对
ALTER INSTANCE RELOAD TLS
语句执行前对系统变量的更改不会更改TLS上下文。在这个点上,这些更改对新连接无效,对应的上下文相关的系统变量和状态变量可能有不同的值。这使您可以在重新配置TLS上下文之前对每个系统变量进行任何必要的更改,然后使用ALTER INSTANCE RELOAD TLS
语句将所有系统变量更改为新的TLS上下文。 -
在
ALTER INSTANCE RELOAD TLS
执行后,相应的系统变量和状态变量具有相同的值。这一直保持到下一个系统变量的更改。
在某些情况下,ALTER INSTANCE RELOAD TLS
本身可能足以重新配置TLS上下文,而不需要更改任何系统变量。假设证书文件ssl_cert
中的证书已经过期。只需将现有文件内容替换为非过期证书,并执行ALTER INSTANCE RELOAD TLS
以使新文件内容被读取并用于新连接。
服务器实现了独立的连接加密配置สำหร于管理连接接口。见管理连接接口支持加密连接。此外,ALTER INSTANCE RELOAD TLS
扩展了一个FOR CHANNEL
子句,允许指定要重新加载TLS上下文的通道(接口)。见第15.1.5节,“ALTER INSTANCE Statement”。没有状态变量暴露管理接口TLS上下文,但是性能chematls_channel_status
表暴露了TLS属性对于主和管理接口。见第29.12.22.9节,“The tls_channel_status Table”。
更新主接口TLS上下文具有以下效果:
-
更新将更改用于主连接接口的TLS上下文用于新连接。
-
更新也将更改用于管理接口的TLS上下文,除非为该接口配置了非默认TLS参数值。
-
更新不影响其他启用的服务器插件或组件,如Group Replication或X Plugin:
-
要将主接口重新配置应用于Group Replication的组通信连接,这些连接从服务器的TLS上下文相关系统变量中获取设置,您需要执行
STOP GROUP_REPLICATION
,然后执行START GROUP_REPLICATION
以停止和重新启动Group Replication。 -
X Plugin在插件初始化时初始化其TLS上下文,如第22.5.3节,“Using Encrypted Connections with X Plugin”中描述。这个上下文不再更改。
-
默认情况下,RELOAD TLS
操作在配置值不允许创建新TLS上下文时回滚,并且没有任何影响。之前的上下文值将继续用于新连接。如果提供了可选的NO ROLLBACK ON ERROR
子句,并且无法创建新上下文,回滚将不发生,而是生成警告,并且在对应接口上的新连接中禁用加密。
启用或禁用连接接口上的加密连接的选项,只有在启动时生效。例如,--tls-version
和--admin-tls-version
选项在启动时确定了主和管理接口是否支持那些TLS版本。这些选项在运行时对ALTER INSTANCE RELOAD TLS
操作无效。例如,您可以将tls_version=''
设置为在启动时禁用主接口的加密连接,然后重新配置TLS并执行ALTER INSTANCE RELOAD TLS
以在运行时启用加密连接。
有关加密连接的客户端选项的完整列表,请见Command Options for Encrypted Connections.
默认情况下,MySQL客户端程序尝试建立加密连接,如果服务器支持加密连接,并且可以通过--ssl-mode
选项进行进一步控制:
-
在缺省情况下,客户端尝试使用加密连接,如果无法建立加密连接,则回退到未加密连接。这也适用于使用明确的
--ssl-mode=PREFERRED
选项。 -
使用
--ssl-mode=REQUIRED
选项,客户端要求加密连接,并且如果无法建立加密连接,则失败。 -
使用
--ssl-mode=DISABLED
选项,客户端使用未加密连接。 -
使用
--ssl-mode=VERIFY_CA
或--ssl-mode=VERIFY_IDENTITY
选项,客户端要求加密连接,并且对服务器CA证书和(在--ssl-mode=VERIFY_IDENTITY
中)服务器主机名在证书中的验证。
默认设置是--ssl-mode=PREFERRED
,这将在其他默认设置不变的情况下建立加密连接。然而,为了防止复杂的中间人攻击,客户端应该验证服务器的身份。设置--ssl-mode=VERIFY_CA
和--ssl-mode=VERIFY_IDENTITY
比默认设置更好,可以防止这种攻击。VERIFY_CA
使客户端检查服务器证书的有效性。VERIFY_IDENTITY
使客户端检查服务器证书的有效性,并且检查客户端使用的主机名是否与服务器证书中的身份相符。为了实现这些设置,您必须首先确保服务器的CA证书在所有使用它的客户端可靠可用,否则将出现可用性问题。因此,它们不是默认设置。
如果服务器端启用require_secure_transport
系统变量,尝试建立未加密的连接将失败。见配置加密连接为必需。
以下客户端选项标识客户端使用的证书和密钥文件,以建立加密连接到服务器。它们类似于服务器端的ssl_ca
、ssl_cert
和ssl_key
系统变量,但--ssl-cert
和--ssl-key
标识客户端公钥和私钥:
-
--ssl-ca
:证书授权机构(CA)证书文件的路径名。这选项,如果使用,必须指定与服务器相同的证书。(--ssl-capath
类似,但指定证书目录的路径名。) -
--ssl-cert
:客户端公钥证书文件的路径名。 -
--ssl-key
:客户端私钥文件的路径名。
相对于默认加密提供的安全性,客户端可以提供与服务器相同的CA证书,并启用主机名身份验证。在这种方式下,服务器和客户端都将信任同一个CA证书,并且客户端验证连接到的主机是否是意图中的主机:
-
要指定CA证书,请使用
--ssl-ca
(或--ssl-capath
),并指定--ssl-mode=VERIFY_CA
. -
要启用主机标识验证,还可以使用
--ssl-mode=VERIFY_IDENTITY
,而不是--ssl-mode=VERIFY_CA
.
使用--ssl-mode=VERIFY_IDENTITY
时,主机标识验证不适用于由服务器自动创建的自签名证书(见第8.3.3.1节,“使用 MySQL 创建 SSL 和 RSA 证书和密钥”)。这些自签名证书不包含服务器名称作为通用名称值。
MySQL 还提供了以下客户端加密连接控制选项:
-
--ssl-cipher
:连接加密的可允许密码列表。 -
--ssl-crl
:证书撤销列表文件的路径名。(--ssl-crlpath
类似,但指定证书撤销列表文件目录的路径名。) -
--tls-version
、--tls-ciphersuites
:允许的加密协议和密码套件;见第8.3.2节,“加密连接 TLS 协议和密码套件”。
根据 MySQL 账户的加密要求,客户端可能需要指定某些选项以使用加密连接到 MySQL 服务器。
假设您想使用没有特殊加密要求的账户或使用CREATE USER
语句创建的账户,该账户包括REQUIRE SSL子句。假设服务器支持加密连接,客户端可以使用加密连接无--ssl-mode
选项或使用明确的--ssl-mode=PREFERRED
选项:
mysql
或:
mysql --ssl-mode=PREFERRED
对于使用REQUIRE SSL子句创建的账户,连接尝试失败如果加密连接不能建立。对于没有特殊加密要求的账户,尝试将回退到未加密连接如果加密连接不能建立。要防止回退并失败,如果加密连接不能建立,请连接:
mysql --ssl-mode=REQUIRED
如果账户有更高的安全要求,其他选项必须指定以建立加密连接:
-
对于使用
REQUIRE X509
子句创建的帐户,客户端必须指定至少--ssl-cert
和--ssl-key
。此外,--ssl-ca
(或--ssl-capath
)被推荐,以便验证服务器提供的公钥证书。例如(请在单行输入):mysql --ssl-ca=ca.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem
-
对于使用
REQUIRE ISSUER
或REQUIRE SUBJECT
子句创建的帐户,加密要求与REQUIRE X509
相同,但是证书必须与帐户定义中指定的发放或主题相匹配。
有关 REQUIRE
子句的详细信息,请见第15.7.1.3节,“CREATE USER 语句”。
MySQL 服务器可以生成客户端证书和密钥文件,以便客户端连接到 MySQL 服务器实例。请见第8.3.3节,“创建 SSL 和 RSA 证书和密钥”。
如果客户端连接到 MySQL 服务器实例使用了 SSL 证书,并且该证书具有 extendedKeyUsage
扩展(X.509 v3 扩展),那么该扩展必须包括客户端身份验证(clientAuth
)。如果 SSL 证书仅用于服务器身份验证(serverAuth
)和其他非客户端证书用途,证书验证失败,客户端连接到 MySQL 服务器实例失败。MySQL 服务器生成的 SSL 证书(如第8.3.3.1节,“使用 MySQL 创建 SSL 和 RSA 证书和密钥”)不包含 extendedKeyUsage
扩展,使用 openssl 命令创建 SSL 证书和密钥,按照第8.3.3.2节,“使用 openssl 创建 SSL 证书和密钥”中的说明。如果您使用自己的客户端证书,请确保 extendedKeyUsage
扩展包括客户端身份验证。
为了防止使用加密和覆盖其他 --ssl-
选项,使用客户端程序时请使用xxx
--ssl-mode=DISABLED
:
mysql --ssl-mode=DISABLED
要确定当前与服务器的连接是否使用加密,可以检查会话值的Ssl_cipher
状态变量。如果值为空,连接不加密。否则,连接加密,值表示加密算法。例如:
mysql> SHOW SESSION STATUS LIKE 'Ssl_cipher';
+---------------+---------------------------+
| Variable_name | Value |
+---------------+---------------------------+
| Ssl_cipher | DHE-RSA-AES128-GCM-SHA256 |
+---------------+---------------------------+
对于mysql客户端,一个alternative是使用STATUS
或\s
命令,并检查SSL
行:
mysql> \s
...
SSL: Not in use
...
或:
mysql> \s
...
SSL: Cipher in use is DHE-RSA-AES128-GCM-SHA256
...
--tls-certificates-enforced-validation
选项启用服务器启动时验证服务器公共密钥证书文件、证书颁发机构(CA)证书文件和证书撤销列表文件:
mysqld --tls-certificates-enforced-validation
如果设置为ON
,服务器在证书无效时停止执行启动。服务器通过提供有效的调试消息、错误消息或两者,以便DBA了解证书的状态。这可能对避免重新启动长时间运行的MySQL服务器,以避免SSL证书过期的情况。
类似地,当您执行ALTER INSTANCE RELOAD TLS
语句以在运行时更改TLS上下文时,新的服务器和CA证书文件将不会被使用。如果验证失败,服务器将继续使用旧证书。在这种情况下,服务器将继续使用旧证书。有关动态更改TLS上下文的信息,请见Server-Side Runtime Configuration and Monitoring for Encrypted Connections。
验证CA证书
对于使用服务器主接口的连接:
-
如果
--ssl_ca
指定了,则服务器将验证相应的CA证书,并向DBA提供适当的警告消息。 -
如果
--ssl_capath
指定了,则服务器将验证该文件夹中的所有CA证书,并向DBA提供适当的警告消息。 -
如果未指定SSL参数,服务器将默认验证数据目录中的CA证书,并向DBA提供适当的警告消息。
对于使用服务器管理接口的连接:
-
如果
--admin_ssl_ca
指定了,则服务器将验证相应的CA证书,并向DBA提供适当的警告消息。 -
如果
--admin_ssl_capath
指定了,则服务器将验证该文件夹中的所有CA证书,并向DBA提供适当的警告消息。 -
如果未指定管理SSL参数,服务器将默认验证数据目录中的CA证书,并向DBA提供适当的警告消息。
验证服务器证书
对于使用服务器主接口的连接:
-
如果没有指定
--ssl_cert
,服务器将验证默认数据目录中的服务器证书。 -
如果指定了
--ssl_cert
,服务器将验证服务器证书,并考虑--ssl_crl
,如果指定了。 -
如果DBA将命令行选项设置为验证证书,那么服务器在遇到无效证书时将停止,并向DBA显示适当的错误信息。否则,服务器将向DBA发送警告信息,并继续运行。
对于使用服务器管理界面连接:
-
如果没有指定
--admin_ssl_cert
,服务器将验证默认数据目录中的服务器证书。 -
如果指定了
--admin_ssl_cert
,服务器将验证服务器证书,并考虑--admin_ssl_crl
,如果指定了。 -
如果DBA将命令行选项设置为验证证书,那么服务器在遇到无效证书时将停止,并向DBA显示适当的错误信息。否则,服务器将向DBA发送警告信息,并继续运行。
对于某些MySQL部署,它可能需要使用加密连接(例如,满足法规要求)。本节讨论了配置设置,用于实现这种功能。这些级别的控制可用:
-
您可以配置服务器,以要求客户端使用加密连接。
-
您可以调用单个客户端程序,以要求使用加密连接,即使服务器允许但不要求加密。
-
您可以配置单个MySQL帐户,以便只能在加密连接中使用。
要要求客户端使用加密连接,请启用require_secure_transport
系统变量。例如,在服务器my.cnf
文件中添加以下行:
[mysqld]
require_secure_transport=ON
或者,您可以在运行时设置和 persist 值,使用以下语句:
SET PERSIST require_secure_transport=ON;
SET PERSIST
将值设置为当前 MySQL 实例。它也将保存值,以便在后续服务器重启时使用。请参阅Section 15.7.6.1, “SET Syntax for Variable Assignment”。
启用require_secure_transport
后,服务器将要求客户端使用某种形式的安全传输方式,并且服务器仅允许使用SSL或共享内存(在Windows上)或套接字文件(在Unix上)的TCP/IP连接。服务器将拒绝非安全连接尝试,这些尝试将以ER_SECURE_TRANSPORT_REQUIRED
错误失败。
要使客户端程序在不管服务器是否要求加密的情况下都使用加密连接,可以使用--ssl-mode
选项的值为REQUIRED
、VERIFY_CA
或VERIFY_IDENTITY
。例如:
mysql --ssl-mode=REQUIRED
mysqldump --ssl-mode=VERIFY_CA
mysqladmin --ssl-mode=VERIFY_IDENTITY
要配置MySQL账户只能通过加密连接使用,包括在CREATE USER
语句中一个REQUIRE
子句,指定加密特征。例如,要要求加密连接并使用有效的X.509证书,可以使用REQUIRE X509
:
CREATE USER 'jeffrey'@'localhost' REQUIRE X509;
关于REQUIRE
子句的详细信息,请参见第15.7.1.3节,“CREATE USER Statement”。
要修改没有加密要求的现有账户,可以使用ALTER USER
语句。