使用加密连接

TiDB 服务端默认采用非加密连接,因而具备监视信道流量能力的第三方可以知悉 TiDB 服务端与客户端之间发送和接受的数据,包括但不限于查询语句内容、查询结果等。若信道是不可信的,例如客户端是通过公网连接到 TiDB 服务端的,则非加密连接容易造成信息泄露,建议使用加密连接确保安全性。

TiDB 服务端支持启用基于 TLS(传输层安全)协议的加密连接,协议与 MySQL 加密连接一致,现有 MySQL 客户端如 MySQL 运维工具和 MySQL 驱动等能直接支持。TLS 的前身是 SSL,因而 TLS 有时也被称为 SSL,但由于 SSL 协议有已知安全漏洞,TiDB 实际上并未支持。TiDB 支持的 TLS/SSL 协议版本为 TLS 1.0、TLS 1.1、TLS 1.2。

使用加密连接后,连接将具有以下安全性质:

  • 保密性:流量明文无法被窃听;
  • 完整性:流量明文无法被篡改;
  • 身份验证(可选):客户端和服务端能验证双方身份,避免中间人攻击。

TiDB 的加密连接支持默认是关闭的,必须在 TiDB 服务端通过配置开启加密连接的支持后,才能在客户端中使用加密连接。另外,与 MySQL 一致,TiDB 加密连接是以单个连接为单位的,并且是可选的,因而对于开启了加密连接支持的 TiDB 服务端,客户端既可以选择通过加密连接安全地连接到该 TiDB 服务端,也可以选择使用普通的非加密连接。大部分 MySQL 客户端默认不采用加密连接,因此一般还要显式地要求客户端使用加密连接。

简单来说,要使用加密连接必须同时满足以下两个条件:

  1. TiDB 服务端配置开启加密连接的支持
  2. 客户端指定使用加密连接

配置 TiDB 启用加密连接支持

在启动 TiDB 时,至少需要在配置文件中同时指定 ssl-certssl-key 参数,才能使 TiDB 服务端接受加密连接。还可以指定 ssl-ca 参数进行客户端身份验证(请参见配置启用身份验证章节)。

  • ssl-cert:指定 SSL 证书文件路径
  • ssl-key:指定证书文件对应的私钥
  • ssl-ca:可选,指定受信任的 CA 证书文件路径

参数指定的文件都为 PEM 格式。另外目前 TiDB 尚不支持加载有密码保护的私钥,因此必须提供一个没有密码的私钥文件。若提供的证书或私钥无效,则 TiDB 服务端将照常启动,但并不支持客户端加密连接到 TiDB 服务端。

上述证书及密钥可以使用 OpenSSL 签发和生成,也可以使用 MySQL 自带的工具 mysql_ssl_rsa_setup 快捷生成:

  1. mysql_ssl_rsa_setup --datadir=./certs

以上命令将在 certs 目录下生成以下文件:

  1. certs
  2. ├── ca-key.pem
  3. ├── ca.pem
  4. ├── client-cert.pem
  5. ├── client-key.pem
  6. ├── private_key.pem
  7. ├── public_key.pem
  8. ├── server-cert.pem
  9. └── server-key.pem

对应的 TiDB 配置文件参数为:

  1. [security]
  2. ssl-cert = "certs/server-cert.pem"
  3. ssl-key = "certs/server-key.pem"

若证书参数无误,则 TiDB 在启动时将会输出 Secure connection is enabled,否则 TiDB 会输出 Secure connection is NOT ENABLED

配置 MySQL 客户端使用加密连接

MySQL 5.7 及以上版本自带的客户端默认尝试使用安全连接,若服务端不支持安全连接则自动退回到使用非安全连接;MySQL 5.7 以下版本自带的客户端默认采用非安全连接。

可以通过命令行参数修改客户端的连接行为,包括:

  • 强制使用安全连接,若服务端不支持安全连接则连接失败 (--ssl-mode=REQUIRED)
  • 尝试使用安全连接,若服务端不支持安全连接则退回使用不安全连接
  • 使用不安全连接 (--ssl-mode=DISABLED)

详细信息请参阅 MySQL 文档中关于客户端配置安全连接的部分。

配置启用身份验证

若在 TiDB 服务端或 MySQL 客户端中未指定 ssl-ca 参数,则默认不会进行客户端或服务端身份验证,无法抵御中间人攻击,例如客户端可能会“安全地”连接到了一个伪装的服务端。可以在服务端和客户端中配置 ssl-ca 参数进行身份验证。一般情况下只需验证服务端身份,但也可以验证客户端身份进一步增强安全性。

  • 若要使 MySQL 客户端验证 TiDB 服务端身份,TiDB 服务端需至少配置 ssl-certssl-key 参数,客户端需至少指定 --ssl-ca 参数,且 --ssl-mode 至少为 VERIFY_IDENTITY。必须确保 TiDB 服务端配置的证书(ssl-cert)是由客户端 --ssl-ca 参数所指定的 CA 所签发的,否则身份验证失败。
  • 若要使 TiDB 服务端验证 MySQL 客户端身份,TiDB 服务端需配置 ssl-certssl-keyssl-ca 参数,客户端需至少指定 --ssl-cert--ssl-key 参数。必须确保服务端配置的证书和客户端配置的证书都是由服务端配置指定的 ssl-ca 签发的。
  • 若要进行双向身份验证,请同时满足上述要求。

注:目前 TiDB 尚不支持强制验证客户端身份,即服务端对客户端的身份验证是可选的。若客户端在 TLS 握手时未出示自己的身份证书,也能正常建立 TLS 连接。

检查当前连接是否是加密连接

可以通过 SHOW STATUS LIKE "%Ssl%"; 了解当前连接的详细情况,包括是否使用了安全连接、安全连接采用的加密协议、TLS 版本号等。

以下是一个安全连接中执行该语句的结果。由于客户端支持的 TLS 版本号和加密协议会有所不同,执行结果相应地也会有所变化。

  1. mysql> SHOW STATUS LIKE "%Ssl%";
  2. ......
  3. | Ssl_verify_mode | 5 |
  4. | Ssl_version | TLSv1.2 |
  5. | Ssl_cipher | ECDHE-RSA-AES128-GCM-SHA256 |
  6. ......

除此以外,对于 MySQL 自带客户端,还可以使用 STATUS\s 语句查看连接情况:

  1. mysql> \s
  2. ...
  3. SSL: Cipher in use is ECDHE-RSA-AES128-GCM-SHA256
  4. ...

支持的 TLS 版本及密钥交换协议和加密算法

TiDB 支持的 TLS 版本及密钥交换协议和加密算法由 Golang 官方库决定。

支持的 TLS 版本

  • TLS 1.0
  • TLS 1.1
  • TLS 1.2

支持的密钥交换协议及加密算法

  • TLS_RSA_WITH_RC4_128_SHA
  • TLS_RSA_WITH_3DES_EDE_CBC_SHA
  • TLS_RSA_WITH_AES_128_CBC_SHA
  • TLS_RSA_WITH_AES_256_CBC_SHA
  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_128_GCM_SHA256
  • TLS_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
  • TLS_ECDHE_RSA_WITH_RC4_128_SHA
  • TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
  • TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305