一、用MySQL鏡像安裝MySQL
#? docker? pull??mysql:8.0
# mkdir? ?-p? /opt/mysqldata? ?/opt/mysqlconfig? ?/opt/sql
#? vim /opt/mysqlconfig/mysqld.cnf
#######################################################
[mysqld]
pid-file? ? ? ? ? ? ? ? ? ? ? ? = /var/run/mysqld/mysqld.pid
socket? ? ? ? ? ? ? ? ? ? ? ? ? = /var/run/mysqld/mysqld.sock
datadir? ? ? ? ? ? ? ? ? ? ? ? = /var/lib/mysql
symbolic-links? ? ? ? ? ? ? ? ? = 0
max_connections? ? ? ? ? ? ?= 2000
user? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = mysql
skip_name_resolve
skip-host-cache
skip-log-bin
character-set-client-handshake? = FALSE
lower_case_table_names? ? ? ? ? = 1
character-set-server? ? ? ? ? ? = utf8
collation-server? ? ? ? ? ? ? ? = utf8_general_ci
init_connect? ? ? ? ? ? ? ? ? ? = "SET NAMES 'utf8'"
default_authentication_plugin? = mysql_native_password
general_log? ? ? = on
general_log_file? = /var/lib/mysql/general.log
log_timestamps? ? = SYSTEM
[mysql]
default-character-set? ? ? ? ? = utf8
[client]
default-character-set? ? ? ? ? = utf8
#######################################################

二、初始化MySQL
# vim mysql8.x_init.sh
###################################################
#!/bin/bash
mysql_ver="8.0"
mysql_datadir="/opt/mysqldata"
mysql_root_pwd="MySQL@123"
registry_addr=""
docker run -itd? \
? --name mysql \
? -p 3306:3306 \
? -e UMASK=0600 \
? -e UMASK_DIR=0700 \
? -e MYSQL_HISTFILE=/dev/null \
? -v ${mysql_datadir}:/var/lib/mysql \
? -v /opt/mysqlconfig/mysqld.cnf:/etc/mysql/conf.d//mysqld.cnf \
? -e MYSQL_ROOT_PASSWORD="${mysql_root_pwd}" \
? mysql:${mysql_ver}
sleep 30
if ss -tan | grep -w "3306" > /dev/null 2>&1; then
? docker stop mysql
? docker rm? mysql
? echo "Mysql init successfully!"
else
? echo "Mysql init failed!"
fi
###################################################

# sh??mysql8.x_init.sh

將MySQL服務(wù)注冊成系統(tǒng)服務(wù)
# cat /etc/systemd/system/mysqld.service
####################################################
[Unit]
Description=MySQL Server
After=network-online.target docker.service
Requires=docker.service
[Service]
Type=simple
ExecStartPre=-/usr/bin/docker rm -f mysql
ExecStart=/usr/bin/docker run \
? --name mysql \
? -p 3306:3306 \
? -e UMASK=0600 \
? -e UMASK_DIR=0700 \
? -e MYSQL_HISTFILE=/dev/null \
? -v /opt/mysqldata:/var/lib/mysql \
? -v /opt/mysqlconfig/mysqld.cnf:/etc/mysql/conf.d//mysqld.cnf \
? -v /opt/sql:/opt/sql \
? -v /etc/localtime:/etc/localtime \
? --security-opt seccomp=unconfined \
? mysql:8.0
ExecStop=/usr/bin/docker stop mysql
LimitNOFILE=65535
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
####################################################

# systemctl daemon-reload
# systemctl start mysqld
# systemctl enable mysqld
# systemctl status mysqld

二、MySQL 不開啟SSL
# cat /opt/mysqlconfig/mysqld.cnf
#######################################################
[mysqld]
pid-file? ? ? ? ? ? ? ? ? ? ? ? = /var/run/mysqld/mysqld.pid
socket? ? ? ? ? ? ? ? ? ? ? ? ? = /var/run/mysqld/mysqld.sock
datadir? ? ? ? ? ? ? ? ? ? ? ? = /var/lib/mysql
symbolic-links? ? ? ? ? ? ? ? ? ? ? = 0
max_connections? ? ? ? ? ? ? ? = 2000
user? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?= mysql
skip_name_resolve
skip-host-cache
skip-log-bin
character-set-client-handshake? = FALSE
lower_case_table_names? ? ? ? ? = 1
character-set-server? ? ? ? ? ? = utf8
collation-server? ? ? ? ? ? ? ? = utf8_general_ci
init_connect? ? ? ? ? ? ? ? ? ? = "SET NAMES 'utf8'"
default_authentication_plugin? = mysql_native_password
general_log? ? ? = on
general_log_file? = /var/lib/mysql/general.log
log_timestamps? ? = SYSTEM
[mysql]
default-character-set? ? ? ? ? = utf8
[client]
default-character-set? ? ? ? ? = utf8
########################################################

后臺通過socket登錄
# docker exec -it mysql mysql -u root -p"MySQL@123"

可以看出,后臺通過socket登錄,是沒有走加密通道的。
后臺通過127.0.0.1登錄
# docker exec -it mysql mysql? ?-h 127.0.0.1? ?-u root -p"MySQL@123"

可以看出,后臺通過127.0.0.1登錄,是加密的。
客戶端遠(yuǎn)程登錄 192.18.1.104? -----> 192.168.1.100:3306



# tail -f /opt/mysqldata/general.log

可以看出,在不開啟MySQL SSL 的情況下,客戶端連接服務(wù)端,是走TCP/IP,沒有加密通道。
MySQL不開啟SSL 的jdbc
MySQL驅(qū)動
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://xx.xx.xx.xx:3306/test?allowMultiQueries=true&useUnicode&characterEncoding=UTF-8&autoReconnect=true&useSSL=false
username=root
password=MySQL@123
MariaDB驅(qū)動
driverClassName=org.mariadb.jdbc.Driver
url=jdbc:mariadb://xx.xx.xx.xx:3306/test?allowMultiQueries=true&useUnicode&characterEncoding=UTF-8&autoReconnect=true&useSSL=false
username=root
password=MySQL@123

三、MySQL 開啟SSL
# vim /opt/mysqlconfig/mysqld.cnf
#############################################################
[mysqld]
pid-file? ? ? ? ? ? ? ? ? ? ? ? ? = /var/run/mysqld/mysqld.pid
socket? ? ? ? ? ? ? ? ? ? ? ? ? ?= /var/run/mysqld/mysqld.sock
datadir? ? ? ? ? ? ? ? ? ? ? ? ? ?= /var/lib/mysql
symbolic-links? ? ? ? ? ? ? ? ? = 0
max_connections? ? ? ? ? ? ?= 2000
user? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = mysql
skip_name_resolve
skip-host-cache
skip-log-bin
character-set-client-handshake? = FALSE
lower_case_table_names? ? ? ? ? ? = 1
character-set-server? ? ? ? ? ? = utf8
collation-server? ? ? ? ? ? ? ? ? ? = utf8_general_ci
init_connect? ? ? ? ? ? ? ? ? ? ? ? ?= "SET NAMES 'utf8'"
default_authentication_plugin? = mysql_native_password
general_log? ? ? = on
general_log_file? = /var/lib/mysql/general.log
log_timestamps? ? = SYSTEM
require_secure_transport = ON
ssl-ca? ? ? ? ? ? ? ? ? = /var/lib/mysql/ca.pem
ssl-cert? ? ? ? ? ? ? ? = /var/lib/mysql/server-cert.pem
ssl-key? ? ? ? ? ? ? ? ? = /var/lib/mysql/server-key.pem
[mysql]
default-character-set? ? ? ? ? = utf8
[client]
default-character-set? ? ? ? ? = utf8
#############################################################

# systemctl? restart mysqld??
# ll /opt/mysqldata/*.pem

后臺通過socket登錄
# docker exec -it mysql mysql -u root -p"MySQL@123"

可以看出,后臺通過socket登錄,是沒有走加密通道的。
后臺通過127.0.0.1登錄
# docker exec -it mysql mysql??-h 127.0.0.1??-u root -p"MySQL@123"

可以看出,后臺通過127.0.0.1登錄,是加密通的,但是沒有啟動SSL。
客戶端遠(yuǎn)程登錄 192.18.1.104? -----> 192.168.1.100:3306



# tail -f /opt/mysqldata/general.log

可以看出,在開啟MySQL SSL 的情況下,客戶端連接服務(wù)端,走加密通道。
四、MySQL 開啟SSL,客戶端jdbc的幾種設(shè)置
關(guān)于開啟 MySQL SSL,客戶端dbc的設(shè)置分以下幾種情況:
1. 服務(wù)端開啟SSL,配置證書,客戶端連服務(wù)端,直接信任證書,不用配置證書
2. 服務(wù)端開啟SSL,配置證書,客戶端連服務(wù)端,配置單向驗(yàn)證客戶端或者服務(wù)端證書
3. 服務(wù)端開啟SSL,配置證書,客戶端連服務(wù)端,配置雙向驗(yàn)證服務(wù)端證書和客戶端證書
MySQL Server端是 x509 的pem格式證書,怎么跟客戶端的 java程序(要連MySQL,jks格式證書)建立證書認(rèn)證關(guān)系?
x509 的 pem格式證書,可以通過轉(zhuǎn)換,變成 jks格式證書。
1. 服務(wù)端開啟SSL,配置證書,客戶端連服務(wù)端,直接信任證書,不用配置證書
MySQL驅(qū)動
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://xx.xx.xx.xx:3306/test?allowMultiQueries=true&useUnicode&characterEncoding=UTF-8&autoReconnect=true&useSSL=true&verifyServerCertificate=false&requireSSL=true
username=root
password=MySQL@123
MariaDB驅(qū)動
driverClassName=org.mariadb.jdbc.Driver
url=jdbc:mariadb://xx.xx.xx.xx:3306/test?allowMultiQueries=true&useUnicode&characterEncoding=UTF-8&autoReconnect=true&useSSL=true&trustServerCertificate=true&requireSSL=true
username=root
password=MySQL@123
關(guān)于證書信任設(shè)置
MySQL:? ? verifyServerCertificate=false
MariaDB:? trustServerCertificate=true

當(dāng)啟用SSL加密并設(shè)置連接字符串屬性trustServerCertificate=false 時(shí)需要做些什么,與設(shè)置trustServerCertificate=true 有什么區(qū)別?
如果當(dāng)使用安全套接字層 (SSL) 對通信層加密時(shí)應(yīng)自動信任服務(wù)器安全套接字層證書,則為“true” , 否則為 false。
此處,我們服務(wù)端,不設(shè)置證書驗(yàn)證,為自動信任服務(wù)器安全套接字層證書。
2. 服務(wù)端開啟SSL,配置證書,客戶端連服務(wù)端,配置單向驗(yàn)證客戶端或者服務(wù)端證書
在 MySQL Server服務(wù)器上
#? mkdir? /root/mysqlSSL
# cp /opt/mysqldata/*.pem? ? ?/root/mysqlSSL/

#? keytool -importcert -alias MySQLCACert? -file ca.pem??-keystore truststore.jks? ?-storepass Truststore@123? ?-noprompt
# keytool -v -list -keystore truststore.jks? -storepass? "Truststore@123"

將?truststore.jks拷貝到客戶端 ,假設(shè)文件路徑為 /opt/cert/truststore.jks
MySQL驅(qū)動
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://xx.xx.xx.xx:3306/test?allowMultiQueries=true&useUnicode&characterEncoding=UTF-8&autoReconnect=true&useSSL=true&verifyServerCertificate=true&requireSSL=true&clientCertificateKeyStoreUrl=file:/opt/cert/truststore.jks&clientCertificateKeyStorePassword="Truststore@123"
username=root
password=MySQL@123
MariaDB驅(qū)動
driverClassName=org.mariadb.jdbc.Driver
url=jdbc:mariadb://xx.xx.xx.xx:3306/test?allowMultiQueries=true&useUnicode&characterEncoding=UTF-8&autoReconnect=true&useSSL=true&trustServerCertificate=false&requireSSL=true&clientCertificateKeyStoreUrl=file:/opt/cert/truststore.jks&clientCertificateKeyStorePassword="Truststore@123"
username=root
password=MySQL@123

當(dāng)啟用SSL加密并設(shè)置連接字符串屬性trustServerCertificate=false 時(shí)需要做些什么,與設(shè)置trustServerCertificate=true 有什么區(qū)別?
如果當(dāng)使用安全套接字層 (SSL) 對通信層加密時(shí)應(yīng)自動信任服務(wù)器安全套接字層證書,則為“true” , 否則為 false。
此處,客戶端務(wù)端設(shè)置了證書驗(yàn)證,通過連接字符串屬性?clientCertificateKeyStoreUrl=file:/opt/cert/?truststore.jks 和 clientCertificateKeyStorePassword=?"Truststore@123"?驗(yàn)證服務(wù)器安全套接字層證書。
3. 服務(wù)端開啟SSL,配置證書,客戶端連服務(wù)端,配置雙向驗(yàn)證服務(wù)端證書和客戶端證書
#? keytool -importcert -alias?MySQLCACert??-file ca.pem??-keystore truststore.jks? ?-storepass?Truststore@123? ?-noprompt
# openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -name "mysqlclient" -passout pass:Keystore@123 -out client-keystore.p12
# keytool -importkeystore -srckeystore client-keystore.p12 -srcstoretype pkcs12 -srcstorepass "Keystore@123" -destkeystore keystore.jks? -deststoretype JKS -deststorepass "Truststore@123"

# keytool -v -list? -keystore truststore.jks? ??-storepass "Truststore@123"
# keytool -v -list? ?-keystore keystore.jks? ? ?-storepass "Truststore@123"


# cat ca.pem
# keytool -export? -alias mysqlcacert? -keystore truststore.jks --storepass "Truststore@123" -rfc

可以看出 ,實(shí)際上事將CA證書 ca.pem 導(dǎo)入到了 truststore.jks中。
# cat client-cert.pem
# keytool -export -alias mysqlclient??-keystore keystore.jks --storepass "Truststore@123" -rfc

可以看出,實(shí)際是將 客戶端證書 client-cert.pem 導(dǎo)入到了 keystore.jks中,當(dāng)然也將 客戶端私鑰 client-key.pem 導(dǎo)入到了keystore.jks中,只是我們沒法直接從?keystore.jks 獲取私鑰內(nèi)容。

注意: 此處?file:///path/to/file?等價(jià)于?file:/path/to/file? ?
將?truststore.jks 和 keystore.jks 拷貝到客戶端 ,假設(shè)文件路徑為??/opt/cert/truststore.jks? /opt/cert/keystore.jks
MySQL驅(qū)動
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://xx.xx.xx.xx:3306/test?allowMultiQueries=true&useUnicode&characterEncoding=UTF-8&autoReconnect=true&verifyServerCertificate=true&useSSL=true&requireSSL=true&clientCertificateKeyStoreUrl=file:/opt/cert/keystore.jks&clientCertificateKeyStorePassword="Keystore@123"&trustCertificateKeyStoreUrl=file:/opt/cert/truststore.jks&trustCertificateKeyStorePassword="Truststore@123"
username=root
password=MySQL@123
MariaDB驅(qū)動
driverClassName=org.mariadb.jdbc.Driver
url=jdbc:mariadb://xx.xx.xx.xx:3306/test?allowMultiQueries=true&useUnicode&characterEncoding=UTF-8&autoReconnect=true&trustServerCertificate=false&useSSL=true&requireSSL=true&clientCertificateKeyStoreUrl=file:/opt/cert/keystore.jks&clientCertificateKeyStorePassword="Keystore@123"&trustCertificateKeyStoreUrl=file:/opt/cert/truststore.jks&trustCertificateKeyStorePassword="Truststore@123"
username=root
password=MySQL@123
用“設(shè)置服務(wù)器身份驗(yàn)證”和“設(shè)置客戶端身份驗(yàn)證”中概述的步驟,以建立雙向雙向身份驗(yàn)證過程,在該過程中,服務(wù)器和客戶端在建立連接之前先對彼此進(jìn)行身份驗(yàn)證。
盡管上述典型設(shè)置在兩端都使用相同的CA證書進(jìn)行相互身份驗(yàn)證,但并非必須如此。?
唯一的要求是,在服務(wù)器中配置的CA證書必須能夠驗(yàn)證客戶端證書,并且導(dǎo)入到客戶端信任庫中的CA證書必須能夠驗(yàn)證服務(wù)器證書。?
兩端使用的兩個(gè)CA證書可以不同。
綜上,我們可以看到:
客戶端不做認(rèn)證 ,直接信任證書,客戶端無需配置證書
單向認(rèn)證(驗(yàn)證服務(wù)端或客戶端),客戶端只需要配置 truststore.jks(truststore-ca.jks或truststore-client.jks)?
雙向認(rèn)證(驗(yàn)證客戶端和者服務(wù)端),?客戶端需要配置truststore.jks(truststore-ca.jks)?和keystore.jks

五、參考
關(guān)于MySQL的jdbc
http://www.itdecent.cn/p/599bc0e31fde
setTrustServerCertificate 方法?
https://docs.microsoft.com/zh-cn/sql/connect/jdbc/reference/settrustservercertificate-method-sqlserverdatasource?view=sql-server-2017
Steps to connect to an AWS RDS MySql server through SSL/TLS
https://developer.jboss.org/message/966980?_sscc=t
常用Keytool 命令
http://www.willrey.com/support/keytool_command.html
用keytool創(chuàng)建keystore和trustsotre文件
http://www.itdecent.cn/p/1b1c9cfa17a4