MySQL的主从复制默认是明文传送的,如果在生产环境中跨网络传送,数据的安全性就无法完全保证,为了解决这一问题,我们需要一种安全的方式进行传送,即基于SSL加密进行数据传输。在进行SSL加密传输时可能需要先了解CA、证书及SSL相关知识才能更好地明白为何基于SSL的传输就会更加安全。CA、证书及SSL相关知识在本章节不会多加一说明,详情可以看本博客提供的“信息安全之PKI及数字证书介绍”和“HTTPS协议和原理介绍”章节。
首先Master和Slave上分别检查SSL状态信息。
mysql> show global variables like '%ssl%';
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| have_openssl | DISABLED |
| have_ssl | DISABLED |
| ssl_ca | |
| ssl_capath | |
| ssl_cert | |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | |
+---------------+----------+
9 rows in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql>showglobalvariableslike'%ssl%';
+---------------+----------+
|Variable_name|Value|
+---------------+----------+
|have_openssl|DISABLED|
|have_ssl|DISABLED|
|ssl_ca||
|ssl_capath||
|ssl_cert||
|ssl_cipher||
|ssl_crl||
|ssl_crlpath||
|ssl_key||
+---------------+----------+
9rowsinset(0.00sec)
确保你看到的是disabled,而不是NO的选项。这表示你的mysql服务器支持ssl,只是没有在启动的时候开启ssl功能,当服务器启动ssl功能的时候,你会看到图中的disabled会显示yes。
下面需要开启支持SSL并设置加密方法,私钥文件等信息。
首先说明一点,我的实验环境把CA服务器、主服务器和从服务器都放在了同一台服务器上面。
1)配置CA服务器
$ cd /etc/pki/CA
$ (umask 077;openssl genrsa -out private/cakey.pem 2048)
$ openssl req -new -x509 -key private/cakey.pem -out cacert.pem -days 3650
$ touch {index.txt,serial}
$ echo 01 > serial
1
2
3
4
5
$cd/etc/pki/CA
$(umask077;opensslgenrsa-outprivate/cakey.pem2048)
$opensslreq-new-x509-keyprivate/cakey.pem-outcacert.pem-days3650
$touch{index.txt,serial}
$echo01>serial
下面是我自签证书时填写的信息:
Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:sh
Locality Name (eg, city) [Default City]:sh
Organization Name (eg, company) [Default Company Ltd]:ej
Organizational Unit Name (eg, section) []:tech
Common Name (eg, your name or your server's hostname) []:mysql.ywnds.com
Email Address []:123@ywnds.com
1
2
3
4
5
6
7
CountryName(2lettercode)[XX]:cn
StateorProvinceName(fullname)[]:sh
LocalityName(eg,city)[DefaultCity]:sh
OrganizationName(eg,company)[DefaultCompanyLtd]:ej
OrganizationalUnitName(eg,section)[]:tech
CommonName(eg,yournameoryourserver'shostname)[]:mysql.ywnds.com
EmailAddress[]:123@ywnds.com
2)Master服务器生成证书
$ mkdir /ssl
$ cd /ssl
$ (umask 077;openssl genrsa -out master.key 2048)
$ openssl req -new -key master.key -out master.csr
1
2
3
4
$mkdir/ssl
$cd/ssl
$(umask077;opensslgenrsa-outmaster.key2048)
$opensslreq-new-keymaster.key-outmaster.csr
3)CA为Master签署证书
$ openssl ca -in /ssl/master.csr -out /ssl/master.crt -days 3650
1
$opensslca-in/ssl/master.csr-out/ssl/master.crt-days3650
PS:需要把证书(master.csr)和key(master.key)从Master服务器上复制到CA服务器上,然后在CA服务器签完证书后把证书master.crt再复制到Master服务器/data/mysql/ssl目录下(我这里是同台服务器,略过此步骤)。
4)Slave服务器生成证书
$ mkdir /ssl
$ cd /ssl
$ (umask 077;openssl genrsa -out slave.key 2048)
$ openssl req -new -key slave.key -out slave.csr
1
2
3
4
$ mkdir/ssl
$cd/ssl
$(umask077;opensslgenrsa-outslave.key2048)
$opensslreq-new-keyslave.key-outslave.csr
5)CA为Slave签署证书
$ openssl ca -in /ssl/slave.csr -out /ssl/slave.crt -days 3650
1
$opensslca-in/ssl/slave.csr-out/ssl/slave.crt-days3650
PS:需要把证书(slave.csr)和key(slave.key)从Slave服务器上复制到CA服务器上,然后在CA服务器签完证书后把证书slave.crt再复制到Slave服务器/data/mysql/ssl目录下(我这里是同台服务器,略过此步骤)。
这里特别要注意一下,两个证书的签署是否成功。另外这几个证书的签署输入信息最好都一样。我这边由于主从都是在同一台机器上进行的,所以Common Name部分是一样的,所以我在为Slave签署证书时报错了,如下:
failed to update database
TXT_DB error number 2
1
2
failedtoupdatedatabase
TXT_DBerrornumber2
主要原因是因为两个证书的主机名一样导致的,解决办法把/etc/pki/CA/index.txt.attr这个文件中的unique_subject = yes改为unique_subject = no。就是不做唯一性限制。再或者把index.txt这个文件删除,然后新建一个。
我的环境是同一台服务器,所以现在我们来看一下相关的文件。
$ ll /data/mysql/ssl
-rw-r--r-- 1 mysql mysql 1375 Nov 24 16:35 cacert.pem
-rw-r--r-- 1 mysql mysql 4547 Nov 24 16:54 master.crt
-rw------- 1 mysql mysql 1675 Nov 24 15:24 master.key
-rw-r--r-- 1 mysql mysql 4547 Nov 24 17:01 slave.crt
-rw------- 1 mysql mysql 1679 Nov 24 15:24 slave.key
1
2
3
4
5
6
$ll/data/mysql/ssl
-rw-r--r--1mysqlmysql1375Nov2416:35cacert.pem
-rw-r--r--1mysqlmysql4547Nov2416:54master.crt
-rw-------1mysqlmysql1675Nov2415:24master.key
-rw-r--r--1mysqlmysql4547Nov2417:01slave.crt
-rw-------1mysqlmysql1679Nov2415:24slave.key
6)将CA证书复制到Master和Slave
$ mkdir /data/mysql/ssl
$ cp /etc/pki/CA/cacert.pem /data/mysql/ssl
1
2
$mkdir/data/mysql/ssl
$cp/etc/pki/CA/cacert.pem/data/mysql/ssl
7)Master和Slave配置SSL
master
[mysqld]
ssl-ca = /data/mysql/ssl/cacert.pem #指定CA文件位置;
ssl-cert = /data/mysql/ssl/master.crt #指定证书文件位置;
ssl-key = /data/mysql/ssl/master.key #指定密钥所在位置;
1
2
3
4
[mysqld]
ssl-ca=/data/mysql/ssl/cacert.pem#指定CA文件位置;
ssl-cert=/data/mysql/ssl/master.crt#指定证书文件位置;
ssl-key=/data/mysql/ssl/master.key#指定密钥所在位置;
slave
[mysqld]
ssl-ca = /data/mysql/ssl/cacert.pem #指定CA文件位置;
ssl-cert = /data/mysql/ssl/slave.crt #指定证书文件位置;
ssl-key = /data/mysql/ssl/slave.key #指定密钥所在位置;
1
2
3
4
[mysqld]
ssl-ca=/data/mysql/ssl/cacert.pem#指定CA文件位置;
ssl-cert=/data/mysql/ssl/slave.crt#指定证书文件位置;
ssl-key=/data/mysql/ssl/slave.key#指定密钥所在位置;
PS:把两个节点都重启一下。
然后再master上面应该会看到如下信息,如果have_openssl和have_ssl的值不为YES,那么你需要看一下错误日志中有什么报错信息(本人在做的时候就碰到了证书签署的时候有问题,导致ssl一直起不来)。
mysql> show global variables like '%ssl%';
+---------------+----------------------------+
| Variable_name | Value |
+---------------+----------------------------+
| have_openssl | YES |
| have_ssl | YES |
| ssl_ca | /data/mysql/ssl/cacert.pem |
| ssl_capath | |
| ssl_cert | /data/mysql/ssl/master.crt |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | /data/mysql/ssl/master.key |
+---------------+----------------------------+
9 rows in set (0.01 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql>showglobalvariableslike'%ssl%';
+---------------+----------------------------+
|Variable_name|Value|
+---------------+----------------------------+
|have_openssl|YES|
|have_ssl|YES|
|ssl_ca|/data/mysql/ssl/cacert.pem|
|ssl_capath||
|ssl_cert|/data/mysql/ssl/master.crt|
|ssl_cipher||
|ssl_crl||
|ssl_crlpath||
|ssl_key|/data/mysql/ssl/master.key|
+---------------+----------------------------+
9rowsinset(0.01sec)
8)Master上创建复制用户
mysql> grant replication slave on *.* to 'backup'@'%' identified by '123456' REQUIRE SSL;
mysql> flush privileges;
1
2
mysql>grantreplicationslaveon*.*to'backup'@'%'identifiedby'123456'REQUIRESSL;
mysql>flushprivileges;
REQUIRE SSL表示此用户必须使用SSL连接。
9)Slave上连接Master配置
mysql> change master to master_host='10.0.60.143',
master_user='backup',
master_password='123456',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154,
MASTER_SSL=1,
MASTER_SSL_CA='/data/mysql/ssl/cacert.pem',
MASTER_SSL_CERT = '/data/mysql/ssl/slave.crt',
MASTER_SSL_KEY = '/data/mysql/ssl/slave.key';
1
2
3
4
5
6
7
8
9
mysql>changemastertomaster_host='10.0.60.143',
master_user='backup',
master_password='123456',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154,
MASTER_SSL=1,
MASTER_SSL_CA='/data/mysql/ssl/cacert.pem',
MASTER_SSL_CERT='/data/mysql/ssl/slave.crt',
MASTER_SSL_KEY='/data/mysql/ssl/slave.key';
PS:需要注意的一点是,如果主从的SSL配置有问题,那么这个change master就会有问题的。
10)查看Slave状态信息
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.60.143
Master_User: backup
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.00001
Read_Master_Log_Pos: 417
Relay_Log_File: relay-log.00001
Relay_Log_Pos: 630
Relay_Master_Log_File: mysql-bin.00001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: test1,test2
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 417
Relay_Log_Space: 1044
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: Yes
Master_SSL_CA_File: /data/mysql/ssl/cacert.pem
Master_SSL_CA_Path:
Master_SSL_Cert: /data/mysql/ssl/slave.crt
Master_SSL_Cipher:
Master_SSL_Key: /data/mysql/ssl/slave.key
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
mysql>showslavestatus\G
***************************1.row***************************
Slave_IO_State:Waitingformastertosendevent
Master_Host:10.0.60.143
Master_User:backup
Master_Port:3306
Connect_Retry:60
Master_Log_File:mysql-bin.00001
Read_Master_Log_Pos:417
Relay_Log_File:relay-log.00001
Relay_Log_Pos:630
Relay_Master_Log_File:mysql-bin.00001
Slave_IO_Running:Yes
Slave_SQL_Running:Yes
Replicate_Do_DB:test1,test2
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno:0
Last_Error:
Skip_Counter:0
Exec_Master_Log_Pos:417
Relay_Log_Space:1044
Until_Condition:None
Until_Log_File:
Until_Log_Pos:0
Master_SSL_Allowed:Yes
Master_SSL_CA_File:/data/mysql/ssl/cacert.pem
Master_SSL_CA_Path:
Master_SSL_Cert:/data/mysql/ssl/slave.crt
Master_SSL_Cipher:
Master_SSL_Key:/data/mysql/ssl/slave.key
然后你可以在master写入数据,看看slave是否正常同步。
以上配置是MySQL 5.7之前的版本,从MySQL 5.7开始,配置SSL复制就更加简洁了。如果仔细阅读MySQL 5.7的安装文档INSTALL-BINARY,会发现5.7的安装文档在初始化数据目录之后还额外多做了一个操作,这是之前版本所没有的操作,而该步骤即是对于SSL的安装与配置。
shell> bin/mysql_ssl_rsa_setup
1
shell>bin/mysql_ssl_rsa_setup
运行完命令mysql_ssl_rsa_setup后会发现数据目录下多出了一些以pem结尾的文件,而这些文件就是开启SSL连接所需要的文件:
server-cert.pem
server-key.pem
client-cert.pem
client-key.pem
ca.pem
ca-key.pem
public_key.pem
private_key.pem
1
2
3
4
5
6
7
8
server-cert.pem
server-key.pem
client-cert.pem
client-key.pem
ca.pem
ca-key.pem
public_key.pem
private_key.pem
PS:如果你是yum安装,那么直接执行mysql_ssl_rsa_setup,就会在/var/log/mysql/目录下就会生成这些文件。
有了这些证书之后,就不需要再自己进行证书的创建了,省去很多事。比如我这里就可以直接把这些证书和key复制到指定的目录使用。
$ cp -frp /var/lib/mysql/{server-cert.pem,server-key.pem,client-cert.pem,client-key.pem,ca.pem,ca-key.pem} /data/mysql/ssl/
1
$cp-frp/var/lib/mysql/{server-cert.pem,server-key.pem,client-cert.pem,client-key.pem,ca.pem,ca-key.pem}/data/mysql/ssl/
然后我们也可以使用客户端直接连接测试SSL连接(MySQL 5.7默认就是使用SSL进行连接)。
$ mysql -ubackup -p -h10.0.60.143 --ssl-ca=/data/mysql/ssl/ca.pem --ssl-cert=/data/mysql/ssl/client-cert.pem --ssl-key=/data/mysql/ssl/client-key.pem
1
$mysql-ubackup-p-h10.0.60.143--ssl-ca=/data/mysql/ssl/ca.pem--ssl-cert=/data/mysql/ssl/client-cert.pem--ssl-key=/data/mysql/ssl/client-key.pem
然后就可以确认是否加密了。
mysql> \s
--------------
mysql Ver 14.14 Distrib 5.7.16, for Linux (x86_64) using EditLine wrapper
Connection id:4
Current database:
Current user:backup@10.0.60.143
SSL:Cipher in use is DHE-RSA-AES256-SHA
1
2
3
4
5
6
7
8
mysql>\s
--------------
mysqlVer14.14Distrib5.7.16,forLinux(x86_64)usingEditLinewrapper
Connectionid:4
Currentdatabase:
Currentuser:backup@10.0.60.143
SSL:CipherinuseisDHE-RSA-AES256-SHA
或
mysql> SHOW STATUS LIKE 'Ssl_cipher';
+---------------+--------------------+
| Variable_name | Value |
+---------------+--------------------+
| Ssl_cipher | DHE-RSA-AES256-SHA |
+---------------+--------------------+
1 row in set (0.00 sec)
1
2
3
4
5
6
7
mysql>SHOWSTATUSLIKE'Ssl_cipher';
+---------------+--------------------+
|Variable_name|Value|
+---------------+--------------------+
|Ssl_cipher|DHE-RSA-AES256-SHA|
+---------------+--------------------+
1rowinset(0.00sec)
我们可以看到SSL字段显示的加密方式为DHE-RSA-AES256-SHA。
如果没有加密,你看到的信息就为SSL: Not in use。
如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。