【MySQL】关于MySQL开启SSL的服务端和客户端设置

一、用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服务注册成系统服务


# 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登录,是加密的。



客户端远程登录 192.18.1.104  -----> 192.168.1.100:3306



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

可以看出,在不开启MySQL SSL 的情况下,客户端连接服务端,是走TCP/IP,没有加密通道。


MySQL不开启SSL 的jdbc


MySQL驱动

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驱动

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。


客户端远程登录 192.18.1.104  -----> 192.168.1.100:3306



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


可以看出,在开启MySQL SSL 的情况下,客户端连接服务端,走加密通道。



四、MySQL 开启SSL,客户端jdbc的几种设置


关于开启 MySQL SSL,客户端dbc的设置分以下几种情况:

1. 服务端开启SSL,配置证书,客户端连服务端,直接信任证书,不用配置证书

2. 服务端开启SSL,配置证书,客户端连服务端,配置单向验证客户端或者服务端证书

3. 服务端开启SSL,配置证书,客户端连服务端,配置双向验证服务端证书和客户端证书



MySQL Server端是 x509 的pem格式证书,怎么跟客户端的 java程序(要连MySQL,jks格式证书)建立证书认证关系?

x509 的 pem格式证书,可以通过转换,变成 jks格式证书。



1. 服务端开启SSL,配置证书,客户端连服务端,直接信任证书,不用配置证书

MySQL驱动

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驱动

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


关于证书信任设置

MySQL:    verifyServerCertificate=false

MariaDB:  trustServerCertificate=true


当启用SSL加密并设置连接字符串属性trustServerCertificate=false 时需要做些什么,与设置trustServerCertificate=true 有什么区别?

如果当使用安全套接字层 (SSL) 对通信层加密时应自动信任服务器安全套接字层证书,则为“true” , 否则为 false。

此处,我们服务端,不设置证书验证,为自动信任服务器安全套接字层证书。




2. 服务端开启SSL,配置证书,客户端连服务端,配置单向验证客户端或者服务端证书


在 MySQL Server服务器上

#  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拷贝到客户端 ,假设文件路径为 /opt/cert/truststore.jks


MySQL驱动

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驱动

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


当启用SSL加密并设置连接字符串属性trustServerCertificate=false 时需要做些什么,与设置trustServerCertificate=true 有什么区别?

如果当使用安全套接字层 (SSL) 对通信层加密时应自动信任服务器安全套接字层证书,则为“true” , 否则为 false。

此处,客户端务端设置了证书验证,通过连接字符串属性 clientCertificateKeyStoreUrl=file:/opt/cert/ truststore.jks 和 clientCertificateKeyStorePassword= "Truststore@123" 验证服务器安全套接字层证书。




3. 服务端开启SSL,配置证书,客户端连服务端,配置双向验证服务端证书和客户端证书


#  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

可以看出 ,实际上事将CA证书 ca.pem 导入到了 truststore.jks中。


# cat client-cert.pem

# keytool -export -alias mysqlclient  -keystore keystore.jks --storepass "Truststore@123" -rfc

可以看出,实际是将 客户端证书 client-cert.pem 导入到了 keystore.jks中,当然也将 客户端私钥 client-key.pem 导入到了keystore.jks中,只是我们没法直接从 keystore.jks 获取私钥内容。


注意: 此处 file:///path/to/file 等价于 file:/path/to/file   


 truststore.jks 和 keystore.jks 拷贝到客户端 ,假设文件路径为  /opt/cert/truststore.jks  /opt/cert/keystore.jks


MySQL驱动

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驱动

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


用“设置服务器身份验证”和“设置客户端身份验证”中概述的步骤,以建立双向双向身份验证过程,在该过程中,服务器和客户端在建立连接之前先对彼此进行身份验证。

尽管上述典型设置在两端都使用相同的CA证书进行相互身份验证,但并非必须如此。 

唯一的要求是,在服务器中配置的CA证书必须能够验证客户端证书,并且导入到客户端信任库中的CA证书必须能够验证服务器证书。 

两端使用的两个CA证书可以不同。



综上,我们可以看到:

客户端不做认证 ,直接信任证书,客户端无需配置证书

单向认证(验证服务端或客户端),客户端只需要配置 truststore.jks(truststore-ca.jks或truststore-client.jks) 

双向认证(验证客户端和者服务端), 客户端需要配置truststore.jks(truststore-ca.jks) 和keystore.jks




五、参考


关于MySQL的jdbc

https://www.jianshu.com/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创建keystore和trustsotre文件

https://www.jianshu.com/p/1b1c9cfa17a4

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351