前提:已安装好数据库,这里以mysql5.7为例
例如:数据库用户名root 密码:123456
数据库data目录:/usr/local/mysql/data
登录mysql命令:mysql -uroot -p
输入密码:123456
Mysql导入证书并开启SSL
一、查看服务端mysql环境
1.查看是否开启了ssl,"have_ssl" 为YES的时候,数据库是开启加密连接方式的
show global variables like '%ssl%';
2.查看数据库版本
select version();
3.查看数据库端口
show variables like 'port';
3306
4.查看数据库存放路径
show variables like 'datadir';
/usr/local/mysql/data
二.生成证书
通过openssl制作生成证书
1.生成一个CA私钥
openssl genrsa 2048 > ca-key.pem
2.通过CA私钥生成数字证书
openssl req -new -x509 -nodes -days 99999 -key ca-key.pem -out ca.pem
3.创建mysql服务器私钥和请求证书
openssl req -newkey rsa:2048 -days 99999 -nodes -keyout server-key.pem -out server-req.pem
4.将私钥转换为RSA私钥文件格式
openssl rsa -in server-key.pem -out server-key.pem
5.用CA证书生成一个服务器的数字证书
openssl x509 -req -in server-req.pem -days 99999 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem
6.创建客户端的RSA私钥和数字证书
openssl req -newkey rsa:2048 -days 99999 -nodes -keyout client-key.pem -out client-req.pem
注意:这里需要填入配置信息
Country Name (2 letter code) [AU]:cn 国家名(2个字母的代号)
State or Province Name (full name) [Some-State]:cq 省
Locality Name (eg, city) []:cq 市
Organization Name (eg, company) [Internet Widgits Pty Ltd]:gs 公司名
Organizational Unit Name (eg, section) []:gs 组织或部门名
Common Name (eg, YOUR name) []:doris_ca 域名或自己名字(ca证书不要用跟服务端证书或者客户端证书一个common name 会报错!)
Email Address []: 邮箱地址(不填直接回车)
A challenge password []:123456 密码
An optional company name []:gs 公司名
注意:这里的Common Name字段需要填写应用服务器的ip或域名,也就是指连接服务器的ip
7.将生成的私钥转换为RAS私钥文件格式
openssl rsa -in client-key.pem -out client-key.pem
8.用CA证书来生成一个客户端的数字证书
openssl x509 -req -in client-req.pem -days 99999 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem
注意:将生成后的客户端证书拷贝到应用服务器上,client-* (如果程序跟数据库不在同一服务器时)
9.查看所有的ssl文件
ca-key.pem
ca.pem
client-cert.pem
client-key.pem
client-req.pem
server-cert.pem
server-key.pem
server-req.pem
10.验证证书
openssl verify -CAfile ca.pem server-cert.pem client-cert.pem
输出结果如下,即为通过:
server-cert.pem: OK
client-cert.pem: OK
如输出结果报错如下:
问题2:error 18 at 0 depth lookup:self signed certificate
需要检查在生产证书时,求你填写的 Common Name
解决方案:
当你在创建ca.csr, server.csr, client.csr时 要求你填写的 Common Name。
ca.pem 的common name 不能和server-cert.pem, client-cert.pem填的相同
三、数据库配置ssl证书
1.将CA证书和服务端ssl文件至mysql数据目录
cp ca.pem server-*.pem /usr/local/mysql/data
注意:/usr/local/mysqldata是数据库的路径,在查看环境时收集到,根据实际情况更换
2.修改msql数据库目录的CA证书和服务端ssl文件所属用户和组
必要时将权限也设置一下:chmod 775 ca.pem server-cert.pem server-key.pem
chown -v mysql.mysql /usr/local/mysql/data{ca,server*}.pem
3.修改mysql配置文件,添加ssl调用配置
vi /etc/my.cnf
[client]
ssl-cert = /usr/local/mysql/data/client-cert.pem
ssl-key = /usr/local/mysql/data/client-key.pem
注意:如果是做了主从,需要把主的证书拷贝到从
[mysqld]
ssl-ca=/usr/local/mysql/data/ca.pem
ssl-cert=/usr/local/mysql/data/server-cert.pem
ssl-key=/usr/local/mysql/data/server-key.pem
4.重启mysql服务,检查数据库ssl是否开启状态,have_openssl 与 have_ssl 值都为YES表示ssl开启成功
service mysqld restart
show variables like '%ssl%';
show variables like 'have%ssl%';
在linux端用root账号进入mysql命令行界面,查看当前版本mysql数据库是否支持ssl,如果出现以下结果表示支持,如果没有考虑更换版本,或者编译一个带有SSL版本的mysql
查看用户是否使用SSL连接
use mysql;
select ssl_type from user where user='test' and host='%';
强制某用户使用SSL连接
ALTER USER 'test'@'%' REQUIRE SSL;
FLUSH PRIVILEGES;
5.测试ssl可用性
grant all on *.* to 'test'@'127.0.0.1' identified by 'test' require SSL;
注意:如果不在本服务器操作,需要将127.0.0.1更换为应用服务器的ip
测试不使用ssl能否连接上
mysql -utest -p -h10.22.xx.xx --ssl-mode=DISABLED;
取消用户使用ssl连接
update user set ssl_type='' where user='test' and host='%';
FLUSH PRIVILEGES;
6.密码连接测试
mysql -utest -ptest -h 127.0.0.1
此时会报错:
ERROR 1045 (28000): Access denied for user 'test1'@'124.222.67.220' (using password: YES)
YES代表需要密码,但没有通过ssl验证
注意:如果MySQL端口不是3306,需要在后面加参数(-P 端口号)
7.通过客户端密钥与证书ssl+密码连接测试,并查看属性
mysql -utest -ptest -h 127.0.0.1 --ssl-cert=client-cert.pem --ssl-key=client-key.pem
进入数据库后,\s查看属性
加密前:
SSL: Not in use
加密后:
SSL: Cipher in use is DHE-RSA-AES256-GCM-SHA384
注意:启动时,需要在client-cert.pem和client-key.pem证书目录下启动,或者在启动时更改证书的路径
例:mysql -utest -ptest -h 127.0.0.1 --ssl-cert=/usr/local/mysql/data/client-cert.pem --ssl-key=/usr/local/mysql/data/client-key.pem
四、JAVA客户端连接数据库
1.要另外指定客户端需要使用加密连接,请启用 require_secure_transport系统变量,ON为开启,OFF默认关闭:
vi /etc/my.cnf
在mysqld下添加
[mysqld]
ssl-ca=/usr/local/mysql/data/ca.pem
ssl-cert=/usr/local/mysql/data/server-cert.pem
ssl-key=/usr/local/mysql/data/server-key.pem
require_secure_transport=ON
查询用户是否强制ssl验证 :select Host,user,ssl_type from User;
要确定当前与服务器的连接是否使用加密,请检查Ssl_cipher状态变量的会话值 。如果该值为空,则连接未加密。否则,连接被加密并且该值指示加密密码。例如:
mysql> SHOW SESSION STATUS LIKE 'Ssl_cipher';
+---------------+---------------------------+
| Variable_name | Value |
+---------------+---------------------------+
| Ssl_cipher | DHE-RSA-AES128-GCM-SHA256 |
+---------------+---------------------------+
对于mysql客户端,另一种方法是使用STATUSor\s 命令并检查该SSL行:
mysql> \s
...
SSL: Not in use
...
mysql> \s
...
SSL: Cipher in use is DHE-RSA-AES128-GCM-SHA256
...
2.使用jdk自带的keytool工具导入mysql客户端证书到密钥仓库,并生成秘钥仓库文件
1.确认是否安装了jdk,并配置了环境变量,如果没有配置环境变量,只能到jdk安装的目录下使用keytoll工具
2.执行shell命令将ca.pem文件导入到密钥仓库,并生成密钥仓库文件
keytool -importcert -alias Cacert -file ca.pem -keystore truststoremysql -storepass 123456
openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -name "mysqlclient" -passout pass:123456 -out client-keystore.p12
keytool -importkeystore -srckeystore client-keystore.p12 -srcstoretype pkcs12 -srcstorepass 123456 -destkeystore keystoremysql -deststoretype JKS -deststorepass 123456
1.找服务端提供三个原始文件
2.生成truststore文件
keytool -importcert -alias Cacert -file ca.pem -keystore truststoremysql -storepass 123456
3.生成keystore文件
openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -name "mysqlclient" -passout pass:123456
keytool -importkeystore -srckeystore client-keystore.p12 -srcstoretype pkcs12 -srcstorepass 123456 -destkeystore keystoremysql -deststoretype JKS -deststorepass 123456
以上两个文件生成的参数可以自己修改,windows环境中没有openssl,在linux环境中执行。红色部分的参数是后面配置要用到的
五、JAVA客户端连接数据库
1.正常的请求如下
spring.datasource.url = jdbc:mysql://1.2.3.4:3306/db?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false
url: jdbc:mysql://10.0.0.199:3306/test?allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=true&userAffectRows=true
username: root
password: 123456
2.ssl双向认证的请求如下
server:
port: 10000
ssl:
cert:
path: /usr/local/mysql/data
config: true&verifyServerCertificate=true&requireSSL=true&clientCertificateKeyStoreUrl=file:${ssl.cert.path}/keystoremysql&clientCertificateKeyStorePassword=123456&trustCertificateKeyStoreUrl=file:${ssl.cert.path}/truststoremysql&trustCertificateKeyStorePassword=123456
spring:
application:
name: dissertation
devtools:
restart:
enabled: true
thymeleaf:
cache: true
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/dissertation?allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=${ssl.config}
username: root
password: 123456
ssl.cert.path = /home/app/cert
ssl.config = true&verifyServerCertificate=true&requireSSL=true&clientCertificateKeyStoreUrl=file:${ssl.cert.path}/keystoremysql&clientCertificateKeyStorePassword=123456&trustCertificateKeyStoreUrl=file:${ssl.cert.path}/truststoremysql&trustCertificateKeyStorePassword=123456
url: jdbc:mysql://127.0.0.1:3306/dissertation?allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=${ssl.config}
username: root
password: 123456
因为加上ssl认证后url太长了,所以提取了两个变量。
ssl.cert.path表示生成的两个证书文件存放路径
ssl.config的value里根据证书生成的参数对应修改,如果不需要ssl认证值设置为false即可。 以上就完成了客户端的配置,如常启动服务,验证连接正常即可。