「MySQL」- 使用 SSL 安全连接及 x509 证书登录

内容:MySQL SSL 加密链接;MySQL 强制证书登录;

MySQL v5.7

代码在本地测试修改,使用到了线上的数据库。开放端口之后,虽然端口改了,密码强度也够可以。但终究不放心;
所以决定本地使用 SSL 安全链接访问远程数据库,并且连接远程数据库强制要求客户端提供证书;

(1). 检查 MySQL 是否支持 SSL

https://dev.mysql.com/doc/refman/5.7/en/openssl-versus-yassl.html

根据官方描述:
MySQL Enterprise Edition binary distributions,编译使用的 OpenSSL 库;
MySQL Community Edition binary distributions,使用的是 yaSSL 库。(我们经常用的就是 Community Edition。我本地测试用的就是这个版本)
MySQL Community Edition source distributions,自己编译的同学就自己看着办吧,编译的时候记得加参数;
参照官方文档「7.4.2 Building MySQL with Support for Secure Connections

检查是否支持 SSL,通过查看 have_ssl 系统变量:

mysql> SHOW VARIABLES LIKE 'have_ssl';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_ssl      | YES   |
+---------------+-------+

如果想看使用了 OpenSSL 还是 yaSSL:

mysql> SHOW STATUS LIKE 'Rsa_public_key';
-- Empty set (0.00 sec)

如果输出为“Empty set (0.00 sec)”则表示使用了 yaSSL 库;如果输出不为空,则表示使用了 OpenSSL 库;

(2). 检查 SSL 的版本

https://dev.mysql.com/doc/refman/5.7/en/secure-connection-protocols-ciphers.html

MySQL 的安全链接使用的是 TLS 协议:

使用了 OpenSSL 1.0.1+ 的库, MySQL 支持 TLSv1、TLSv1.1、TLSv1.2;

如果使用了 yaSSL 库, MySQL 支持 TLSv1、TLSv1.1;

查看 MySQL 支持的 TLS 协议版本:

mysql> SHOW GLOBAL VARIABLES LIKE 'tls_version';
-- +---------------+---------------+
-- | Variable_name | Value         |
-- +---------------+---------------+
-- | tls_version   | TLSv1,TLSv1.1 |
-- +---------------+---------------+
-- 1 row in set (0.00 sec)

如果要修改 tls_version 的值,需要修改 my.cnf。在 mysqld 章节加入参数,如下:

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

(3). 配置安全链接

创建 SSL 相关文件

创建 CA 证书

openssl genrsa 2048 > ca-key.pem
openssl req -new -x509 -nodes -days 3600 -key ca-key.pem -out ca.pem

创建服务端证书

openssl req -newkey rsa:2048 -days 3600 -nodes -keyout server-key.pem -out server-req.pem
openssl rsa -in server-key.pem -out server-key.pem
openssl x509 -req -in server-req.pem -days 3600 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem

创建客户端证书

openssl req -newkey rsa:2048 -days 3600 -nodes -keyout client-key.pem -out client-req.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -req -in client-req.pem -days 3600 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem

配置 MySQL

[mysqld]
ssl-ca=ca.pem
ssl-cert=server-cert.pem
ssl-key=server-key.pem

(4). 检查配置是否成功

使用 SSL 连接 MySQL:

mysql --ssl-ca=ca.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem -u root -p -hlocalhost

使用 “Ssl_cipher” 变量来检查当前链接是否加密:

mysql> SHOW STATUS LIKE 'Ssl_cipher';
-- +---------------+--------------------+
-- | Variable_name | Value              |
-- +---------------+--------------------+
-- | Ssl_cipher    | DHE-RSA-AES256-SHA |
-- +---------------+--------------------+
-- 1 row in set (0.01 sec)

如果没有使用 SSL 链接,“Ssl_cipher” 的值为空;

也可以使用 \s 来查看:

mysql> \s
......
SSL:                    Cipher in use is DHE-RSA-AES256-SHA
......

如果没有使用 SSL 链接,“SSL: Not in use”;

(5). 设置帐号登录时提供证书

前几步只是设置,还有一件正事没做:强制要求帐号登录时提供证书:


alter user demo@'%' identified by 'demo,&r' require X509;

(6). 关于 PHP 中使用证书访问 MySQL

“You are enforcing ssl conection via unix socket. Please consider switching ssl off as it does not make connection via unix socket any more secure.” – 如果通过 unix socket 访问数据库,鉴于是本地连接,未跨网络,因此无需使用 ssl 连接;