解决MySQL8.0及其更高版本的两个安全问题——及其配置MySQL实现SSL/TLS加密通信、caching_sha2_password通信
一、问题描述
《1》在使用客户端登录MySQL8.0及其更高版本时提示“mysql: [Warning] Using a password on the command line interface can be insecure.”
《2》MySQL8.0及其更高版本的数据库做主从复制时报错“[ERROR] [MY-010584] [Repl] Replica I/O for channel '': Error connecting to source 'repl@192.168.1.37:13337'. This was attempt 23/86400, with a delay of 60 seconds between attempts. Message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection. Error_code: MY-002061”。
二、问题分析
问题一:在登录时候直接指定明文密码登录MySQL数据库,会提示不安全的错误(可能原因是MySQL的安全认证不能直接明文密码登录;或者是密码输入错误)。
问题二:主从复制时提示授权插件caching_sha2_password报告错误,需要请求安全的连接。
三、解决方法
3.1、解决登录提示不安全提示问题
3.1.1、不指定明文密码
/usr/local/mysql/mysql-8.0.43/bin/mysql -uroot -p
3.1.2、修改MySQL的配置文件跳过授权检查(可解决忘记用户密码情况)
#1-修改MySQL的配置文件(如:/usr/local/mysql/mysql-8.0.43/etc/my.cnf)添加跳过权限检查的参数
vi /usr/local/mysql/mysql-8.0.43/etc/my.cnf#2-在my.cnf文件中添加【skip-grant-tables】参数后保存退出#3-重启MySQL服务让配置生效
systemctl stop mysqld.service
systemctl start mysqld.service#4-直接使用root用户无密码登录
/usr/local/mysql/mysql-8.0.43/bin/mysql -u root#5-登录到MySQL后修改root用户或指定用户密码
flush privileges;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'qwas%1357';
flush privileges;#6-再次进入my.cnf文件中将【skip-grant-tables】参数删除或注释后保存退出再重启MySQL服务
systemctl stop mysqld.service
systemctl start mysqld.service
3.2、解决主从复制提示要求安全连接问题
MySQL :: MySQL 8.0 参考手册 :: 3.5 MySQL 8.0 中的更改https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password
3.2.1、临时方案
使用MySQL8.0之前旧版本默认身份验证插件【mysql_native_password】;虽然这样可以解决问题,但是会导致MySQL8.0及其更高版本的身份验证安全性能下降了,所以不是长久方案,是临时解决方案。
#1-使用MySQL8.0之前低版本的默认身份验证插件(修改MySQL的配置文件my.cnf在末尾添加上如下参数)后重启MySQL服务
mysql_native_password=on#2-直接修改主从复制用户的权限
ALTER USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
flush privileges;
3.2.2、获取MySQL的Master主库公钥【首选】
由于MySQL8.0及其更高版本的默认身份验证插件是【caching_sha2_password】,因此我们可以直接使用【get_master_public_key】参数来获取master主库的公钥,从而完成安全连接。
#在从库进行的主从配置操作
#1-停止从库复制主库
stop replica;
#2-重置从库配置
reset replica all;#3-重新配置从库连接主库(这个配置内容查看MySQL的主库日志文件获取)【开启了GTID】
change replication source to
source_host='192.168.1.36',
source_port=13337,
source_user='repl',
source_password='repl_passwd',
source_auto_position=1,
get_source_public_key=1;#4-启动从库复制主库
start replica;#5-查看从库主从复制状态
show replica status\G;
3.2.3、配置使用SSL/TLS连接
6.3.1 配置 MySQL 使用加密连接_MySQL 8.0 参考手册https://mysql.net.cn/doc/refman/8.0/en/using-encrypted-connections.html
《1》证书的获取:
①可以直接使用MySQL自己生成的SSL/TLS证书【/usr/local/mysql/mysql-8.0.43/data】;
②也可以自己使用OpenSSL创建自签名证书
#自己使用OpenSSL创建自签名证书流程#2-生成SSL/TLS的证书密钥对(可使用OpenSSL生成)
mkdir -p dbsecrets
cd dbsecrets/#2.2-生成私钥_privatekey(服务端与客户端)【用于签名和解密的核心文件,保存在本地,必须严格保密】
openssl genrsa -out server-key.pem 2048
openssl genrsa -out client-key.pem 2048#2.3-生成证书请求_CSR【是由私钥生成的包含公钥与身份信息的请求文件。通常提交给证书颁发机构(CA)进行签名;使用私钥进行签名,保证请求的合法性。】
openssl req -new -key server-key.pem -out server.csr -subj "/C=cn/ST=yn/L=kunming/O=ck/OU=dev/CN=cksite"
openssl req -new -key client-key.pem -out client.csr -subj "/C=cn/ST=yn/L=kunming/O=ck/OU=dev/CN=ckclient"#2.4-生成CA证书【注意:这里需要输入和确认CA证书的密码(密码要求大于等于8位)】
openssl req -new -x509 -keyout ca-key.pem -out ca-cert.pem -days 3650 -subj "/C=cn/ST=yn/L=kunming/O=ck/OU=dev/CN=ck"#2.5-签发证书_CRT【包含了身份信息、公钥和数字签名的结构化文件。可以由自签生成,也可以由 CA 签发。】
openssl x509 -req -in server.csr -CA ca-cert.pem -CAkey ca-key.pem -out server-cert.pem -days 3650 -CAcreateserial
openssl x509 -req -in client.csr -CA ca-cert.pem -CAkey ca-key.pem -out client-cert.pem -days 3650 -CAcreateserial#注意:国家(C)、省份(ST)、组织(O)必需和CA证书里的相同,不然后面签发会报错
#C=单位的两字母国家代码
#ST=州或省份名称
#L=城市或区域名称
#O=组织名称
#OU=组织单位名称
#CN=域名或者名字与姓氏
《2》给MySQL配置SSL/TLS证书且实现主从同步都使用SSL/TLS
#我们这里以MySQL自身生成的SSL/TLS证书为例配置SSL/TLS连接说明【我们将证书内容都存放在【/usr/local/mysql/mysql-8.0.43/dbsecrets/】目录中】#0-在主库和从库的MySQL中创建存储主库的密钥目录
cd /usr/local/mysql/mysql-8.0.43
mkdir -p dbsecrets
chown -R mysql:mysql ./dbsecrets#1-进入MySQL主库(192.168.1.36)的data路径中将主库中的供从库或客户端使用SSL/TLS内容发送一份给从库(192.168.1.37\192.168.1.38)或客户端
cd /usr/local/mysql/mysql-8.0.43/data
scp ca.pem client-cert.pem client-key.pem root@192.168.1.37:/usr/local/mysql/mysql-8.0.43/dbsecrets
scp ca.pem client-cert.pem client-key.pem root@192.168.1.38:/usr/local/mysql/mysql-8.0.43/dbsecrets#1.1-进入主库的data路径中将主库的所有SSL/TLS内容都原样复制一份到【/usr/local/mysql/mysql-8.0.43/dbsecrets】目录中,并对密钥内容检查授权
cp -p ca-key.pem ca.pem client-cert.pem client-key.pem private_key.pem public_key.pem server-cert.pem server-key.pem ../dbsecrets/
cd /usr/local/mysql/mysql-8.0.43/dbsecrets
chmod +r client-key.pem#1.2-进入从库的data路径中将从库中除了【ca.pem client-cert.pem client-key.pem】其余都原样复制一份到【/usr/local/mysql/mysql-8.0.43/dbsecrets/】目录中
cp -p ca-key.pem private_key.pem public_key.pem server-cert.pem server-key.pem ../dbsecrets/
cd /usr/local/mysql/mysql-8.0.43/dbsecrets
chmod +r client-key.pem #2-修改主库配置文件【/usr/local/mysql/mysql-8.0.43/etc/my.cnf】重新配置SSL/TLS
vi /usr/local/mysql/mysql-8.0.43/etc/my.cnf
#配置SSL/TLS
ssl_ca=/usr/local/mysql/mysql-8.0.43/dbsecrets/ca.pem
ssl_cert=/usr/local/mysql/mysql-8.0.43/dbsecrets/server-cert.pem
ssl_key=/usr/local/mysql/mysql-8.0.43/dbsecrets/server-key.pem#2.1-从库中配置文件【/usr/local/mysql/mysql-8.0.43/etc/my.cnf】里面添加主库发送来的SSL/TLS内容
vi /usr/local/mysql/mysql-8.0.43/etc/my.cnf
#配置SSL/TLS
ssl_ca=/usr/local/mysql/mysql-8.0.43/dbsecrets/ca.pem
ssl_cert=/usr/local/mysql/mysql-8.0.43/dbsecrets/client-cert.pem
ssl_key=/usr/local/mysql/mysql-8.0.43/dbsecrets/client-key.pem#3-最后就是重启所有MySQL
systemctl restart mysqld.service#4-登录到所有MySQL数据库中查看是否都开启了SSL/TLS【】
/usr/local/mysql/mysql-8.0.43/bin/mysql -uroot -p
show variables like '%ssl%';#6-在从库Mysql中配置主从复制内容
stop replica;change replication source to
source_host='192.168.1.36',
source_port=13337,
source_user='repl',
source_password='repl_passwd',
source_auto_position=1,
source_ssl=1,
source_ssl_ca='/usr/local/mysql/mysql-8.0.43/dbsecrets/ca.pem',
source_ssl_cert='/usr/local/mysql/mysql-8.0.43/dbsecrets/client-cert.pem',
source_ssl_key='/usr/local/mysql/mysql-8.0.43/dbsecrets/client-key.pem';start replica;
show replica status\G;
注意:从库在配置了SSL/TLS后登录MySQL查看ssl时【show variables like '%ssl%';】若出现“
have_openssl | DISABLED |
have_ssl | DISABLED ”
则表示当前从库配置文件【/usr/local/mysql/mysql-8.0.43/etc/my.cnf】配置的SSL/TLS有问题,我们仔细观察发现,从库应该配置的SSL/TLS是【ca.pem 、client-cert.pem 、client-key.pem】才对,而我们这里则是server的内容因此不对,需要修改my.cnf文件内容后重启MySQL【systemctl restart mysql.service】后再次执行【show variables like '%ssl%';】命令查看即可解决,如下图所示:
3.2.4、主从复制的一些问题及其处理方法
《1》在从库连接主库时报错“Got fatal error 1236 from source when reading data from binary log: 'Cannot replicate because the source purged required binary logs. Replicate the missing transactions from elsewhere, or provision a new replica from backup. Consider increasing the source's binary log expiration period. The GTID set sent by the replica is 'e5c87ab9-a4da-11f0-ac56-000c299307b6:1-7', and the missing transactions are '138e66dd-a381-11f0-8f08-000c296d209f:1-3''” 【Got fatal error 1236 xxx】错误的原因是【主库已经清除了从库所需的二进制日志,这可能会导致主从复制中断】。
解决方法:
用备份重新初始化从库
#用主库备份重新初始化从库的步骤#0-在主库查看当前状态信息,获取恢复的内容的GTID节点
show master status;#2-停止从库复制
stop replica;#3-从主库备份的GTID节点恢复数据(注意:当恢复时报错“ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed: the added gtid set must not overlap with @@GLOBAL.GTID_EXECUTED”需要执行【RESET MASTER;】命令后再次重试)
set global gtid_purged="138e66dd-a381-11f0-8f08-000c296d209f:1-3,
83e288e3-a4ba-11f0-9623-000c296d209f:1-6";
《2》在主从复制时报错“Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction '83e288e3-a4ba-11f0-9623-000c296d209f:8' at source log mysql-bin.000053, end_log_pos 529. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.”是由于从库的SQL执行出错了,造成主从不一致。
解决办法是:先停止该从节点的主从同步然后重置该从节点的Master内容后重新拉取最新的主库数据,最后再次启动主从同步。
#解决主从同复制同步时从库的SQL执行报错问题流程#1-登录故障从节点的MySQL
/usr/local/mysql/mysql-8.0.43/bin/mysql -u root -p#2-查看故障节点的主从同步状态信息,可以查看到对应的报错内容(也可以查看该从节点的日志信息查看到)
show replica status\G;#3-停止该故障节点的主从同步
stop replica;#3-根据报错信息将该从节点的内容连接主库更新到最新后再启动主从同步查看状态即可
#注意:在从库连接主库直接更新同步到最新数据时,报错“ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed: the new value must be a superset of the old value”需要执行【RESET MASTER;】命令重置即可
set global gtid_purged="83e288e3-a4ba-11f0-9623-000c296d209f:8";
start replica;
show replica status\G;