MySQL启用的SSL连接的思考与实践

MySQL启用的SSL连接的思考与实践

SSL

由于工作上的业务发展和等保三级合规的要求,需要考虑为MySQL启用SSL连接,那么今天就来说说这个怎么玩。其实一个月前已经在实现了用docker跑MySQL SSL了,只不过后到今天才有时间静下心来总结一下。

有必要使用为MySQL启用SSL吗?

先来了解一下SSL吧:

SSL(Secure Socket Layer:安全套接字层)利用数据加密、身份验证和消息完整性验证机制,为基于TCP等可靠连接的应用层协议提供安全性保证。

SSL协议提供的功能主要有:

​ 1、 数据传输的机密性:利用对称密钥算法对传输的数据进行加密。
2.、身份验证机制:基于证书利用数字签名方法对服务器和客户端进行身份验证,其中客户端的身份验证是可选的。
3、 消息完整性验证:消息传输过程中使用MAC算法来检验消息的完整性。

如果用户的传输不是通过SSL的方式,那么其在网络中数据都是以明文进行传输的,而这给别有用心的人带来了可乘之机。所以,现在很多大型网站都开启了SSL功能。同样地,在我们数据库方面,如果客户端连接服务器获取数据不是使用SSL连接,那么在传输过程中,数据就有可能被窃取。

所以,我认为启用SSL是一个不错的选择。

那么SSL如何工作在MySQL中的

这里分两说,因为工作中我涉及到MySQL5.6和MySQL 5.7两个版本,它们在SSL连接的实现上也有少许区别。

MySQL5.6的SSL

MySQL 5.6中的SSL文档非常详细,它解释了SSL的工作原理。但首先让我们说清楚一点:MySQL支持使用TLS(传输层安全性)协议在客户端和服务器之间建立安全(加密)连接。 TLS有时被称为SSL(安全套接字层),但MySQL实际上并不使用SSL协议进行安全连接,因为它提供弱加密。

因此,当我们有人说MySQL正在使用SSL时,它实际上意味着它正在使用TLS。您可以使用以下命令检查您使用的协议:

1
2
3
4
5
6
show status like 'Ssl_version';
+---------------+---------+
| Variable_name | Value |
+---------------+---------+
| Ssl_version | TLSv1.2 |
+---------------+---------+

TLS使用加密算法来确保可以信任通过公共网络接收的数据。它具有检测数据更改,丢失或重放的机制。 TLS还包含使用X509标准提供身份验证的算法。 X509可以识别互联网上的某个人。在基本术语中,应该有一些称为“证书颁发机构”(或CA)的实体,它将电子证书分配给需要它们的任何人。证书依赖于具有两个加密密钥(公钥和密钥)的非对称加密算法。证书所有者可以将证书提供给另一方作为身份证明。证书由其所有者的公钥组成。使用该公钥加密的任何数据只能使用由证书所有者持有的相应密钥解密。

MySQL5.6只支持TLSv1,MySQL5.7则支持TLSv1, TLSv1.1, and TLSv1.2 。

MySQL支持使用TLS协议的加密连接:
使用OpenSSL 1.0.1或更高版本编译时,MySQL支持TLSv1,TLSv1.1和TLSv1.2协议。
当使用捆绑版本的yaSSL进行编译时,MySQL支持TLSv1和TLSv1.1协议。

使用SSL配置服务器时,客户端必须具有客户端证书。获得后,它可以使用SSL连接到服务器。MySQL5.6的客户端必须指定密钥和证书。否则,我们无法使用SSL连接到服务器。 如下:

my.cnf配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[mysqld]
skip-host-cache
skip-name-resolve
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
#log-error = /var/log/mysql/error.log
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
ssl-ca=/etc/mysql/certs/ca.pem
ssl-cert=/etc/mysql/certs/MySQL1-cert.pem
ssl-key=/etc/mysql/certs/MySQL1-key.pem

[client]
ssl-ca=/etc/mysql/certs/ca.pem
ssl-cert=/etc/mysql/certs/MySQL-client-cert.pem
ssl-key=/etc/mysql/certs/MySQL-client-key.pem

客户端连接:

1
mysql --ssl-ca=/etc/mysql/certs/ca.pem  --ssl-cert=/etc/mysql/certs/MySQL-client-cert.pem --ssl-key=/etc/mysql/certs/MySQL-client-key.pem

MySQL5.7的SSL

默认情况下,如果服务器支持加密连接,MySQL程序将尝试使用加密进行连接,如果无法建立加密连接,则会回退到未加密的连接。有关影响加密连接使用的选项的信息 。
MySQL基于每个连接执行加密,并且对给定用户使用加密可以是可选的或强制的。可以根据各个应用程序的要求选择加密或未加密的连接。在CREATE USER的时候,有SSL相关的参数可以选择,这个创建用户参数取决于其用户连接时,是否必须使用密钥文件连接MySQL。

这些在官方文档里面都有说明,可以去详细了解下。这里就不铺开了。

MySQL 5.7中的加密连接支持进行了一些改进。以下时间表总结了这些变化:

5.7.3:在客户端,明确的–ssl选项不再是建议性的,而是规定性的。如果服务器支持加密连接,则客户端程序可以通过仅指定–ssl选项来要求加密连接。 (以前,客户端必须指定–ssl-ca选项,或者所有三个–ssl-ca, –ssl-key和–ssl-cert选项。)连接尝试失败如果无法建立加密连接。客户端的其他–ssl-xxx选项在没有–ssl的情况下是建议性的:客户端尝试使用加密进行连接,但如果无法建立加密连接,则会回退到未加密的连接。

5.7.5:默认情况下启用服务器端–ssl选项值。 对于使用OpenSSL编译的服务器,auto_generate_certs和sha256_password_auto_generate_rsa_keys系统变量可用于在启动时启用SSL / RSA证书和密钥文件的自动生成和自动发现。对于证书和密钥自动发现,如果启用了–ssl并且未给出其他–ssl-xxx选项以明确配置加密连接,则服务器会在启动时尝试自动启用对加密连接的支持,如果它发现必需的证书和密钥文件在数据目录中。

5.7.6:mysql_ssl_rsa_setup实用程序可用于手动生成SSL / RSA证书和密钥文件。启动时自动发现SSL / RSA文件将扩展为适用于所有服务器,无论是使用OpenSSL还是使用yaSSL编译。 (这意味着无需启用auto_generate_certs即可进行自动发现。) 如果服务器在启动时发现CA证书是自签名的,则会向错误日志写入警告。 (如果服务器自动创建证书,则证书是自签名的,或者使用mysql_ssl_rsa_setup手动创建证书。)

5.7.7:如果服务器支持加密连接,则C客户端库会默认尝试建立加密连接。这会影响客户程序,如下所示:

  • 如果没有–ssl选项,客户端将尝试使用加密进行连接,如果无法建立加密连接,则会回退到未加密的连接。
  • 显式–ssl选项或同义词(–ssl = 1, - enable-ssl)的存在是规定性的:客户端需要加密连接,如果无法建立,则会失败。
  • 使用–ssl = 0选项或同义词(–skip-ssl, - disable-ssl),客户端使用未加密的连接.此更改还会影响基于C客户端库的MySQL连接器的后续版本:Connector / C,Connector / C ++和Connector / ODBC。

5.7.8:require_secure_transport系统变量可用于控制与服务器的客户端连接是否必须使用某种形式的安全传输。

5.7.10:TLS协议支持从TLSv1扩展到TLSv1.1和TLSv1.2。服务器端的tls_version系统变量和客户端的–tls-version选项可以选择支持级别。

5.7.11:MySQL客户端程序支持–ssl-mode选项,使您可以指定与服务器的连接的安全状态。 –ssl-mode选项包括客户端–ssl和–ssl-verify-server-cert选项的功能。因此,不推荐使用–ssl和–ssl-verify-server-cert,MySQL 8.0中已经删除它们。

好,上边说了这么多,各位都看明白了吗?不明白也没关系,我下面用docker来演示

坑点:我用许多客户端应用程序对它进行了测试,无论是MySQL5.6或5.7,MySQL客户端连接服务端时必须指定客户端密钥。没有密钥,无法连接到服务器。某些较旧的应用程序可能不支持此功能。 所以啊,官档说的也不一定全对。

实践

这里以MySQL5.6为例

1、建立目录

1
2
3
4
# mkdir -pv mysql_ssl_{data,config,cert}
mkdir: created directory 'mysql_ssl_data'
mkdir: created directory 'mysql_ssl_config'
mkdir: created directory 'mysql_ssl_cert'

准备好数据、证书、配置等文件

2、启动容器

1
docker run --name mysql5.6_ssl_test -v /data/mysql_ssl_data/:/var/lib/mysql -v /data/mysql_ssl_config/my.cnf:/etc/my.cnf -v /data/mysql_ssl_cert/:/etc/mysql/certs -p 3306:3306 mysql:5.6.40

3、因为MySQL5.6默认用户是不开启SSL认证的,需要进行如下操作:

1
2
3
4
5
#修改已存在用户 
GRANT USAGE ON *.* TO `user`@`%` REQUIRE X509;
#新建必须使用SSL用户
grant all privileges on *.* to 'user'@'%' identified by '111111' with grant option;
GRANT USAGE ON *.* TO `user`@`%` REQUIRE X509;

对于具有REQUIRE X509的帐户,客户端必须指定要连接的–ssl-key和–ssl-cert选项。 (建议但不要求也指定–ssl-ca,以便验证服务器提供的公共证书。)对于ISSUER和SUBJECT也是如此,因为这些REQUIRE选项意味着X509的要求。

好,现在无论是用图形化工具还是使用命令行客户端,都必须指定客户端的证书及密钥文件,加上账户密码,才能连接登录MySQL了。

参考资料:

https://www.cnblogs.com/mysql-dba/p/7061300.html

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

https://dev.mysql.com/doc/refman/5.6/en/encrypted-connection-protocols-ciphers.html

https://dev.mysql.com/doc/refman/5.6/en/encrypted-connections.html

https://dev.mysql.com/doc/refman/5.7/en/encrypted-connections.html

0%