MySQL 5.7 的tls传输加密
MySQL 5.7 的tls传输加密
ssl传输加密
MySQL 5.7.6或以上版本
(1)创建证书开启SSL验证
--安装openssl
yum install -y openssl
openssl version
OpenSSL 1.0.1e-fips 11 Feb 2013
--安装证书
/usr/local/mysql/bin/mysql_ssl_rsa_setup --datadir=/data/mysql/mysql3306/data
--修改权限
chown -R mysql:mysql /data/mysql/mysql3306/data
pwd
/data/mysql/mysql3306/data
[root@VM_45_133_centos Wed Jun 28 10:51:22 data]# ll
total 1024072
-rw-r----- 1 mysql mysql 56 Jun 19 17:56 auto.cnf
-rw------- 1 root root 1679 Jun 28 10:48 ca-key.pem
-rw-r--r-- 1 root root 1074 Jun 28 10:48 ca.pem
-rw-r--r-- 1 root root 1078 Jun 28 10:48 client-cert.pem
-rw------- 1 root root 1679 Jun 28 10:48 client-key.pem
-rw-r----- 1 mysql mysql 672 Jun 28 10:47 ib_buffer_pool
-rw-r----- 1 mysql mysql 1048576000 Jun 28 10:47 ibdata1
drwxr-x--- 2 mysql mysql 4096 Jun 19 17:57 mysql
drwxr-x--- 2 mysql mysql 4096 Jun 19 17:57 performance_schema
-rw------- 1 root root 1679 Jun 28 10:48 private_key.pem
-rw-r--r-- 1 root root 451 Jun 28 10:48 public_key.pem
drwxr-x--- 2 mysql mysql 4096 Jun 23 10:48 school
-rw-r--r-- 1 root root 1078 Jun 28 10:48 server-cert.pem
-rw------- 1 root root 1675 Jun 28 10:48 server-key.pem
drwxr-x--- 2 mysql mysql 12288 Jun 19 17:57 sys
-rw-r----- 1 mysql mysql 418 Jun 20 14:14 VM_45_133_centos.log
客户端连接需要的证书,当然不用证书也是可以的
-rw-r--r-- 1 root root 1074 Jun 28 10:48 ca.pem
-rw-r--r-- 1 root root 1078 Jun 28 10:48 client-cert.pem
-rw------- 1 root root 1679 Jun 28 10:48 client-key.pem
-rw------- 1 root root 1679 Jun 28 10:48 private_key.pem
服务器上的证书
-rw-r--r-- 1 root root 1074 Jun 28 10:48 ca.pem
-rw------- 1 root root 1679 Jun 28 10:48 ca-key.pem
-rw-r--r-- 1 root root 451 Jun 28 10:48 public_key.pem
-rw-r--r-- 1 root root 1078 Jun 28 10:48 server-cert.pem
-rw------- 1 root root 1675 Jun 28 10:48 server-key.pem
--修改my.cnf
#########SSL#############
ssl-ca = /data/mysql/mysql3306/data/ca.pem
ssl-cert = /data/mysql/mysql3306/data/server-cert.pem
ssl-key = /data/mysql/mysql3306/data/server-key.pem
(2)重启mysql
/etc/init.d/mysql stop
/etc/init.d/mysql start
--查看ssl参数状态,查看have_ssl,为YES,这表示已经开始支持SSL了
show global variables like '%ssl%';
+---------------+--------------------------------------------+
| Variable_name | Value |
+---------------+--------------------------------------------+
| have_openssl | YES |
| have_ssl | YES |
| ssl_ca | /data/mysql/mysql3306/data/ca.pem |
| ssl_capath | |
| ssl_cert | /data/mysql/mysql3306/data/server-cert.pem |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | /data/mysql/mysql3306/data/server-key.pem |
+---------------+--------------------------------------------+
show global status like '%ssl%';
+--------------------------------+--------------------------+
| Variable_name | Value |
+--------------------------------+--------------------------+
| Com_show_processlist | 0 |
| Ssl_accept_renegotiates | 0 |
| Ssl_accepts | 0 |
| Ssl_callback_cache_hits | 0 |
| Ssl_cipher | |
| Ssl_cipher_list | |
| Ssl_client_connects | 0 |
| Ssl_connect_renegotiates | 0 |
| Ssl_ctx_verify_depth | 0 |
| Ssl_ctx_verify_mode | 0 |
| Ssl_default_timeout | 0 |
| Ssl_finished_accepts | 0 |
| Ssl_finished_connects | 0 |
| Ssl_server_not_after | Jun 26 02:48:05 2027 GMT |
| Ssl_server_not_before | Jun 28 02:48:05 2017 GMT |
| Ssl_session_cache_hits | 0 |
| Ssl_session_cache_misses | 0 |
| Ssl_session_cache_mode | Unknown |
| Ssl_session_cache_overflows | 0 |
| Ssl_session_cache_size | 0 |
| Ssl_session_cache_timeouts | 0 |
| Ssl_sessions_reused | 0 |
| Ssl_used_session_cache_entries | 0 |
| Ssl_verify_depth | 0 |
| Ssl_verify_mode | 0 |
| Ssl_version | |
+--------------------------------+--------------------------+
查看mysql支持的SSL版本
show global variables like 'tls_version';
+---------------+---------------+
| Variable_name | Value |
+---------------+---------------+
| tls_version | TLSv1,TLSv1.1 |
+---------------+---------------+
(3)配置SSL用户
取消ssl验证
grant all privileges on *.* to abcssl@'%' identified by '123456' require none;
alter user abcssl@'%' require none;
--强制ssl验证,即使设置了强制ssl,在登录时候使用--ssl-mode=disable依然可以避开ssl验证
grant all privileges on *.* to abcssl@'%' identified by '123465' require ssl;
alter user abcssl@'%' require ssl;
查看是否开启强制用户使用SSL
select user,host,ssl_type,ssl_cipher from mysql.user;
+-----------+-----------+----------+------------+
| user | host | ssl_type | ssl_cipher |
+-----------+-----------+----------+------------+
| root | % | | |
| mysql.sys | localhost | | |
| abcssl | % | ANY | |
+-----------+-----------+----------+------------+
(4)连接数据库的时候,带上SSL
不指定客户端证书方式
5.6
--ssl、--disable-ssl、--skip-ssl:在mysql5.7是将被废弃的选项,将来版本不再支持,建议使用--ssl-mode选项,
/usr/local/mysql/bin/mysql -uroot -p -h127.0.0.1 --ssl 默认为1
/usr/local/mysql/bin/mysql -uroot -p -h127.0.0.1 --ssl=0
/usr/local/mysql/bin/mysql -uroot -p -h127.0.0.1 --ssl=1 默认为1
/usr/local/mysql/bin/mysql -uroot -p -h127.0.0.1 --disable-ssl
/usr/local/mysql/bin/mysql -uroot -p -h127.0.0.1 --skip-ssl
5.7
/usr/local/mysql/bin/mysql -uroot -p -h127.0.0.1 --ssl-mode=disable
/usr/local/mysql/bin/mysql -uroot -p -h127.0.0.1 --ssl-mode=required 默认required
从另一台机器连接过去也可以ssl加密,表明不需要安装客户端证书的
/usr/local/mysql/bin/mysql -uroot -p -h10.105.45.133 --ssl-mode=required
指定客户端证书方式,5.6的方式,5.7也可以用
/usr/local/mysql/bin/mysql --ssl-ca=/data/mysql/mysql3306/data/ca.pem \
--ssl-cert=/data/mysql/mysql3306/data/client-cert.pem \
--ssl-key=/data/mysql/mysql3306/data/client-key.pem \
-uroot -p -h127.0.0.1
(5)连接验证连接是否用了ssl
\s == status
--------------
/usr/local/mysql/bin/mysql Ver 14.14 Distrib 5.7.18, for linux-glibc2.5 (x86_64) using EditLine wrapper 客户端版本
Connection id: 69
Current database:
Current user: root@127.0.0.1
SSL: Cipher in use is DHE-RSA-AES256-SHA
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 5.7.18-log MySQL Community Server (GPL)
Protocol version: 10
Connection: 127.0.0.1 via TCP/IP
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: utf8
Conn. characterset: utf8
TCP port: 3306
Uptime: 28 min 14 sec
Threads: 2 Questions: 1755 Slow queries: 0 Opens: 114 Flush tables: 1 Open tables: 102 Queries per second avg: 1.036
--------------
简单来说,要使用加密连接必须同时满足以下两个条件:
服务端配置开启加密连接ssl的支持
要不要使用加密连接由客户端决定,mysql命令行客户端默认使用加密连接,如果不想使用加密连接,客户端ssl=false就可以了,但是只影响当前客户端,其他客户端不影响
JDBC客户端的解决方法
连接字符串url中加入ssl=true或false:
url=jdbc:mysql://127.0.0.1:3306/framework?characterEncoding=utf8&useSSL=true
主从复制,使用ssl
https://www.modb.pro/db/44867
主从复制使用SSL/TLS连接的配置方法与client/server使用SSL/TLS连接的配置方法类似。
在master节点,可以在配置文件中配置以下内容和数据目录有对应的文件:
[mysqld] ssl-ca=ca.pem ssl-cert=server-cert.pem ssl-key=server-key.pem
在slave节点上,类似的可以在配置文件中如下配置:
[client] ssl-ca=ca.pem ssl-cert=client-cert.pem ssl-key=client-key.pem
使用CHANGE MASTER TO
语句来指定master 信息时,只需要添加MASTER_SSL选项即可开启SSL/TLS协议进行Binlog同步:
mysql> CHANGE MASTER TO -> MASTER_HOST=’master_hostname’, -> MASTER_USER=’repl’, -> MASTER_PASSWORD=’password’, -> MASTER_SSL=1;
当设置MASTER_SSL=1时,其行为与--ssl-mode=PREFERRED的行为一致,即优先尝试SSL/TLS连接,若无法建立则再尝试非SSL/TLS连接。
同理,如果设置MASTER_SSL=0时,其行为与--ssl-mode=DISABLED一致。
同样的,如果没有在配置文件中指明所使用的PEM文件,可以在CHANGE MASTER
时进行指定,语法如下:
-> MASTER_SSL_CA = ‘ca_file_name’, -> MASTER_SSL_CAPATH = ‘ca_directory_name’, -> MASTER_SSL_CERT = ‘cert_file_name’, -> MASTER_SSL_KEY = ‘key_file_name’,
同理,如果在CHANGE MASTER语句中指定了MASTER_SSL_CA或是MASTER_SSL_CAPATH,或是在配置文件中配置了对应参数,
则其行为与client端配置了--ssl-mode=VERIFY_CA行为一致。
如果希望验证hostname的有效性,可以添加如下参数,其行为则与client端配置了--ssl-mode=VERIFY_IDENTITY一致:
-> MASTER_SSL_VERIFY_SERVER_CERT=1,
如果希望确保从库的复制是使用SSL/TLS建立的连接,可以在创建主从复制账号时,指定REQUIRE SSL选项。
mysql> CREATE USER ‘repl’@’%.example.com’ IDENTIFIED BY ‘password’ REQUIRE SSL;
mysql> GRANT REPLICATION SLAVE ON . TO ‘repl’@’%.example.com’;
如果复制账号已经存在,可以通过以下语句添加REQUIRE SSL选项:
mysql> ALTER USER ‘repl’@’%.example.com’ REQUIRE SSL;
手动构建CA,使用openssl自建CA系统。
由于发布版本的MySQL在编译时开启了SSL/TLS,因此在安装包安装成功并启动MySQL之后,会自动创建SSL/TLS相关的PEM格式文件。具体细节可以参考MySQL官方文档相关章节。本章节主要介绍如何使用openssl自建CA系统。
下面的命令会生成CA秘钥和证书、server端的秘钥和证书,以及client端的秘钥和证书。在生成过程中,需要命令行输入一些参数,在测试时候,可以直接输入空,即按回车键跳过;但是在生产环境中,需要输入对应的正确信息。
# Create CA certificate openssl genrsa 2048 > ca-key.pem openssl req -new -x509 -nodes -days 3600 -key ca-key.pem -out ca.pem # Create server certificate, remove passphrase, and sign it # server-cert.pem = public key, server-key.pem = private key 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 # Create client certificate, remove passphrase, and sign it # client-cert.pem = public key, client-key.pem = private key 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
生成上述文件后,可以对其进行验证:
openssl verify -CAfile ca.pem server-cert.pem client-cert.pem
也可以查看各个证书中的CN等信息:
openssl x509 -text -in ca.pem openssl x509 -text -in server-cert.pem openssl x509 -text -in client-cert.pem
为了更加直观的比较禁用与开启SSL/TLS协议后网络链路上传输的数据的变化,对TCP层进行抓包。下面是执行同一语句,在禁用和开启SSL/TLS协议情况下的抓包情况:
(client:172.17.0.4 server:172.17.0.3 SQL:select * from ght.test_ssl)
下面是开启SSL/TLS后的抓包结果:
省略
下面是禁用SSL/TLS的抓包结果:
# TCP Hex Data From: 172.17.0.4:46862 To: 172.17.0.3:3306 Payload (27 bytes): 00000 17 00 00 00 03 73 65 6c 65 63 74 20 2a 20 66 72 …..select * fr 00016 6f 6d 20 74 65 73 74 5f 73 73 6c om test_ssl #TCP Hex Data From: 172.17.0.3:3306 To: 172.17.0.4:46862 Payload (69 bytes): 00000 01 00 00 01 01 2b 00 00 02 03 64 65 66 03 67 68 …..+….def.gh 00016 74 08 74 65 73 74 5f 73 73 6c 08 74 65 73 74 5f t.test_ssl.test_ 00032 73 73 6c 01 61 01 61 0c 3f 00 0b 00 00 00 03 03 ssl.a.a.?……. 00048 50 00 00 00 02 00 00 03 01 31 07 00 00 04 fe 00 P……..1…… 00064 00 02 00 00 00 …..
上述对比很直观的看到,没有使用SSL/TLS的数据传输,抓包结果中不仅可以获取发送的SQL语句,也可以获得结果集。
网络传输的数据轻易的可以被监听、甚至修改等,可见在传输敏感数据的时候,开启SSL/TLS的重要性。
MySQL中的CA相关文件
通过上述描述,应该已经很清楚MySQL为了支持SSL/TLS所构建的CA系统,以及所需要的这些PEM格式文件的作用了,下面再次进行简单阐述:
文件名称 | CA系统中的地位 | 作用 |
ca-key.pem | CA系统的私钥 | 用来对client/server的证书进行签名 |
ca.pem | CA 系统的公钥 | 用来验证client/server的证书是否是 CA颁发的 |
client/server-cert.pem | client/server的证书 | 用来验证消息发送方的身份的有效性 |
client/server-key.pem | client/server的私钥 | 用来对数据的摘要进行签名 |