MySQL 使用 SSL 连接配置详解
查看是否支持SSL
首先在MySQL上执行如下命令,查询是否MySQL支持SSL:
mysql>SHOWVARIABLESLIKE'have_ssl'; +---------------+-------+ |Variable_name|Value| +---------------+-------+ |have_ssl|YES| +---------------+-------+ 1rowinset(0.02sec)
当have_ssl为YES时,表示此时MySQL服务已经支持SSL了.如果是DESABLE,则需要在启动MySQL服务时,使能SSL功能.
使用OpenSSL创建SSL证书和私钥
首先我们需要使用openssl来创建服务器端的证书和私钥.我使用的openssl版本为:
>>>/usr/local/Cellar/openssl/1.0.2j/bin/opensslversion OpenSSL1.0.2j26Sep2016
新建一个~/temp/cert目录,用于存放生成的证书和私钥
mkdir~/temp/cert cd~/temp/cert
创建CA私钥和CA证书
然后,我们先来生成一个CA私钥:
opensslgenrsa2048>ca-key.pem
当有了一个CA私钥,我们接下来就可以使用这个私钥生成一个新的数字证书:
opensslreq-sha1-new-x509-nodes-days3650-keyca-key.pem>ca-cert.pem
执行这个命令时,会需要填写一些问题,随便填写就可以了.例如:
>>>opensslreq-sha1-new-x509-nodes-days3650-keyca-key.pem>ca-cert.pem Youareabouttobeaskedtoenterinformationthatwillbeincorporated intoyourcertificaterequest. WhatyouareabouttoenteriswhatiscalledaDistinguishedNameoraDN. Therearequiteafewfieldsbutyoucanleavesomeblank Forsomefieldstherewillbeadefaultvalue, Ifyouenter'.',thefieldwillbeleftblank. ----- CountryName(2lettercode)[AU]:CN StateorProvinceName(fullname)[Some-State]:Beijing LocalityName(eg,city)[]:Beijing OrganizationName(eg,company)[InternetWidgitsPtyLtd]:xys OrganizationalUnitName(eg,section)[]:xys CommonName(e.g.serverFQDNorYOURname)[]:xys EmailAddress[]:yongshun1228@gmail.com
执行上述命令后,我们就有了一个CA私钥和一个CA证书.
创建服务器端的RSA私钥和数字证书
接着,我们需要创建服务器端的私钥和一个证书请求文件,命令如下:
opensslreq-sha1-newkeyrsa:2048-days3650-nodes-keyoutserver-key.pem>server-req.pem
上面这个命令会生成一个新的私钥(server-key.pem),同时会使用这个新私钥来生成一个证书请求文件(server-req.pem).
上面这个命令同样需要回答几个问题,随便填写即可.不过需要注意的是,Achallengepassword这一项需要为空.
即:
>>>opensslreq-sha1-newkeyrsa:2048-days3650-nodes-keyoutserver-key.pem>server-req.pem Generatinga2048bitRSAprivatekey .................+++ ..+++ writingnewprivatekeyto'server-key.pem' ----- Youareabouttobeaskedtoenterinformationthatwillbeincorporated intoyourcertificaterequest. WhatyouareabouttoenteriswhatiscalledaDistinguishedNameoraDN. Therearequiteafewfieldsbutyoucanleavesomeblank Forsomefieldstherewillbeadefaultvalue, Ifyouenter'.',thefieldwillbeleftblank. ----- CountryName(2lettercode)[AU]:CN StateorProvinceName(fullname)[Some-State]:Beijing LocalityName(eg,city)[]:Beijing OrganizationName(eg,company)[InternetWidgitsPtyLtd]:xys OrganizationalUnitName(eg,section)[]:xys CommonName(e.g.serverFQDNorYOURname)[]:xys EmailAddress[]:yongshun1228@gmail.com Pleaseenterthefollowing'extra'attributes tobesentwithyourcertificaterequest Achallengepassword[]: Anoptionalcompanyname[]:
下一步,我们需要将生成的私钥转换为RSA私钥文件格式:
opensslrsa-inserver-key.pem-outserver-key.pem
最后一步,我们需要使用原先生成的CA证书来生成一个服务器端的数字证书:
opensslx509-sha1-req-inserver-req.pem-days3650-CAca-cert.pem-CAkeyca-key.pem-set_serial01>server-cert.pem
上面的命令会创建以服务器端的数字证书文件.
创建客户端的RSA私钥和数字证书
和服务器端所执行的命令类似,我们也需要为客户端生成一个私钥和证书请求文件,命令如下:
opensslreq-sha1-newkeyrsa:2048-days3650-nodes-keyoutclient-key.pem>client-req.pem
同样地,我们需要将生成的私钥转换为RSA私钥文件格式:
opensslrsa-inclient-key.pem-outclient-key.pem
最后,我们也需要为客户端创建一个数字证书:
opensslx509-sha1-req-inclient-req.pem-days3650-CAca-cert.pem-CAkeyca-key.pem-set_serial01>client-cert.pem
使用工具创建证书与私钥
前面我们介绍了如何使用OpenSSL来创建SSL连接的私钥和证书文件,现在我们来看一个更简单的方法.
在MySQL5.7中,提供了一个名为mysql_ssl_rsa_setup的工具,通过它,我们可以很方便地创建SSL连接所需要的各种文件:
mkdir~/temp/cert cd~/temp/cert mysql_ssl_rsa_setup--datadir./
上面的命令中,--datadir表示生成的文件的目录.
当执行了上述命令后,也会生成八个文件:
ca-key.pem ca.pem client-cert.pem client-key.pem private_key.pem public_key.pem server-cert.pem server-key.pem
这些文件和我们使用OpenSSL所创建的那八个文件的作用是一样的,这里就不再详述了.
SSL配置
在前面的步骤中,我们已经生成了8个文件,分别是:
ca-cert.pem:CA证书,用于生成服务器端/客户端的数字证书.
ca-key.pem:CA私钥,用于生成服务器端/客户端的数字证书.
server-key.pem:服务器端的RSA私钥
server-req.pem:服务器端的证书请求文件,用于生成服务器端的数字证书.
server-cert.pem:服务器端的数字证书.
client-key.pem:客户端的RSA私钥
client-req.pem:客户端的证书请求文件,用于生成客户端的数字证书.
client-cert.pem:客户端的数字证书.
接下来我们就需要分别配置服务器端和客户端.
服务器端配置
服务器端需要用到三个文件,分别是:CA证书,服务器端的RSA私钥,服务器端的数字证书,我们需要在[mysqld]配置域下添加如下内容:
[mysqld] ssl-ca=/etc/mysql/ca-cert.pem ssl-cert=/etc/mysql/server-cert.pem ssl-key=/etc/mysql/server-key.pem
接着我们还可以更改bind-address,使MySQL服务可以接收来自所有ip地址的客户端,即:
bind-address=*
当配置好后,我们需要重启MySQL服务,使能配置.
最后一步,我们添加一个需要使用SSL才可以登录的帐号,来验证一下我们所配置的SSL是否生效:
GRANTALLPRIVILEGESON*.*TO'ssl_test'@'%'IDENTIFIEDBY'ssl_test'REQUIRESSL; FLUSHPRIVILEGES;
当配置好后,使用root登录MySQL,执行showvariableslike'%ssl%'语句会有如下输出:
mysql>showvariableslike'%ssl%'; +---------------+-----------------+ |Variable_name|Value| +---------------+-----------------+ |have_openssl|YES| |have_ssl|YES| |ssl_ca|ca.pem| |ssl_capath|| |ssl_cert|server-cert.pem| |ssl_cipher|| |ssl_crl|| |ssl_crlpath|| |ssl_key|server-key.pem| +---------------+-----------------+ 9rowsinset(0.01sec)
客户端配置
客户端配置相对简单一些.首先我们需要拷贝ca-cert.pem,client-cert.pem和client-key.pem这三个文件到客户端主机中,然后我们可以执行如下命令来使用SSL连接MySQL服务:
mysql--ssl-ca=/path/to/ca-cert.pem--ssl-cert=/path/to/client-cert.pem--ssl-key=/path/to/client-key.pem-hhost_name-ussl_test-p
除了上述的使用命令行方式配置SSL外,我们也可以使用配置文件的方式.即在~/.my.cnf文件中添加如下内容即可:
[client] ssl-ca=/path/to/ca-cert.pem ssl-cert=/path/to/client-cert.pem ssl-key=/path/to/client-key.pem
当连接成功后,我们执行如下指令
mysql>\s -------------- mysqlVer14.14Distrib5.7.17,forLinux(x86_64)usingEditLinewrapper Connectionid:14 Currentdatabase: Currentuser:ssl_test@172.17.0.4 SSL:CipherinuseisDHE-RSA-AES256-SHA Currentpager:stdout Usingoutfile:'' Usingdelimiter:; Serverversion:5.7.17MySQLCommunityServer(GPL) Protocolversion:10 Connection:test_dbviaTCP/IP Servercharacterset:latin1 Dbcharacterset:latin1 Clientcharacterset:latin1 Conn.characterset:latin1 TCPport:3306 Uptime:1hour2min9sec Threads:1Questions:23Slowqueries:0Opens:126Flushtables:3Opentables:0Queriespersecondavg:0.006 --------------
如果输出中有SSL:CipherinuseisDHE-RSA-AES256-SHA之类的信息,则表示已经使用SSL来连接了.
在Docker中使能MySQLSSL连接
上面我们简单介绍了一下如果使能MySQLSSL连接,那么现在我们使用Docker来具体的实战一把吧!
首先拉取最新的MySQL镜像:
dockerpullmysql
然后需要准备一下挂载到Docker容器的目录结构:
>>>cd~/temp >>>tree . ├──cert │├──ca-key.pem │├──ca.pem │├──client-cert.pem │├──client-key.pem │├──private_key.pem │├──public_key.pem │├──server-cert.pem │└──server-key.pem ├──config │└──my.cnf └──db 3directories,9files
在temp目录下有三个子目录:
cert目录用于存放我们先前生成的证书和私钥信息;
config目录用于存放MySQL服务的配置文件
db目录是用于存放MySQL的数据.
下一步我们需要使用如下命令启动MySQL容器:
dockerrun--rm--nametest_db-p10000:3306-eMYSQL_ROOT_PASSWORD=root-v/Users/xiongyongshun/temp/db:/var/lib/mysql-v/Users/xiongyongshun/temp/config:/etc/mysql/conf.d-v/Users/xiongyongshun/temp/cert:/etc/mysql/certmysql:latest
我们在上面的命令中,我们分别挂载了cert,config,db这三个宿主机上的目录到MySQL容器中.
启动了MySQL服务后,可以先使用root帐号登录MySQL,来检查MySQL服务此时是否已经开启了SSL功能:
dockerrun-it--linktest_db:test_db--rmmysqlsh-c'execmysql-uroot-p-htest_db'
登录成功后,我们在MySQL中执行如下指令:
mysql>showvariableslike'%ssl%'; +---------------+---------------------------------+ |Variable_name|Value| +---------------+---------------------------------+ |have_openssl|YES| |have_ssl|YES| |ssl_ca|/etc/mysql/cert/ca-cert.pem| |ssl_capath|| |ssl_cert|/etc/mysql/cert/server-cert.pem| |ssl_cipher|| |ssl_crl|| |ssl_crlpath|| |ssl_key|/etc/mysql/cert/server-key.pem| +---------------+---------------------------------+ 9rowsinset(0.01sec)
有上面的输出后,表明此时MySQL服务已经使用SSL功能了.
接着下一步,我们按照前面所提到的,创建一个仅仅可以使用SSL登录的帐号,来检验我们的配置是否有效:
GRANTALLPRIVILEGESON*.*TO'ssl_test'@'%'IDENTIFIEDBY'ssl_test'REQUIRESSL; FLUSHPRIVILEGES;[code]
上面的命令创建了一个帐号名为ssl_test,密码为ssl_test,并且不限制登录主机ip的帐号.
这些都配置成功后,我们再启动一个MySQL客户端容器:
[code]dockerrun-it--linktest_db:test_db--rm-v/Users/xiongyongshun/temp/cert:/etc/mysql/certmysqlsh-c'execmysql--ssl-ca=/etc/mysql/cert/ca-cert.pem--ssl-cert=/etc/mysql/cert/client-cert.pem--ssl-key=/etc/mysql/cert/client-key.pem-htest_db-ussl_test-p'