SSL(Secure Sockets Layer 安全套接层),是为网络通信提供安全及数据完整性的一种安全协议,其利用公开密钥数据加密(Encryption)技术,确保数据在网络上之传输过程中不会被截取及窃听。

SSL协议提供的服务主要有:

    认证用户和服务器,确保数据发送到正确的客户机和服务器;

    加密数据以防止数据中途被窃取;

    维护数据的完整性,确保数据在传输过程中不被改变。

为了在MySQL服务器和客户端之间建立SSL联接,服务器系统必须满足:

    操作系统安装有OpenSSL或yaSSL;

    安装的MySQL版本必须支持SSL。

    本文中使用OpenSSL。

一、前提

    1. 检查操作系统是否满足要求:

        shell>rpm -qa | grep openssl #检查是否安装OpenSSL。MySQL需要openssl的共享库。

        //如果没有安装,则进行安装,官网: ​​http://www.openssl.org​

    2. 检查数据库是否满足要求

        mysql> show global variables like ‘have%ssl’; #检查是否支持ssl。NO表示不支

        //持,DISABLE表示支持但未使用,如何启用见下文。

        +---------------+----------+

        | Variable_name | Value    |

        +---------------+----------+

        | have_openssl  | DISABLED |

        | have_ssl      | DISABLED |

        +---------------+----------+


        如果是使用编译好的二进制,默认都支持,如果自行编译,针对5.5版本,需要使用

        cmake . -DWITH_SSL=system选项。

        为使客户端能够使用SSL方式进行连接,需要配置合适的证书和密钥文件,以及为用

        户授予合适的权限。


二、为MySQL生成证书和密钥

    1. 前提

        shell>mkdir -p /db/ssl

        shell>cd /db/ssl


    2. 创建认证机构的数字认证证书,后续服务器端和客户端的证书都使用该认证机构进行签署。

        shell>openssl genrsa 2048 > ca-key.pem

        Generating RSA private key, 2048 bit long modulus

        ………+++

        …………………………………………………………………………………………………..+++

        e is 65537 (0×10001)

    

        shell>openssl req -new -x509 -nodes -days 3600 -key ca-key.pem -out ca-cert.pem

        You are about to be asked to enter information that will be incorporated

        into your certificate request.

        What you are about to enter is what is called a Distinguished Name or a DN.

        There are quite a few fields but you can leave some blank

        For some fields there will be a default value,

        If you enter ‘.’, the field will be left blank.

        Country Name (2 letter code) [GB]:CN

        State or Province Name (full name) [Berkshire]:Beijing

        Locality Name (eg, city) [Newbury]:Beijing

        Organization Name (eg, company) [My Company Ltd]:CA

        Organizational Unit Name (eg, section) []:

        Common Name (eg, your name or your server’s hostname) []:

        Email Address []:


    3. 创建服务器端证书

        shell>openssl req -newkey rsa:2048 -days 3600 -nodes -keyout server-key.pem \

        -out server-req.pem

        Generating a 2048 bit RSA private key

        ……………….+++

        …………………………+++

        writing new private key to ‘server-key.pem’


        You are about to be asked to enter information that will be incorporated

        into your certificate request.

        What you are about to enter is what is called a Distinguished Name or a DN.

        There are quite a few fields but you can leave some blank

        For some fields there will be a default value,

        If you enter ‘.’, the field will be left blank.


        Country Name (2 letter code) [GB]:CN

        State or Province Name (full name) [Berkshire]:Beijing

        Locality Name (eg, city) [Newbury]:Beijing

        Organization Name (eg, company) [My Company Ltd]:CH

        Organizational Unit Name (eg, section) []:

        Common Name (eg, your name or your server’s hostname) []:mysqlserver

        Email Address []:

        Please enter the following ‘extra’ attributes

        to be sent with your certificate request

        A challenge password []:abc123

        An optional company name []:


        shell>openssl rsa -in server-key.pem -out server-key.pem 

        //移除server-key中的passphrase[可选]

        writing RSA key

        

        shell>openssl x509 -req -in server-req.pem -days 3600 -CA ca-cert.pem -CAkey \

        ca-key.pem -set_serial 01 -out server-cert.pem 

        //签署服务端证书

        Signature ok

        subject=/C=CN/ST=Hangzhou/L=Hangzhou/O=CH/CN=mysqlserver

        Getting CA Private Key

        

    4. 创建客户端证书

        shell>openssl req -newkey rsa:2048 -days 3600 -nodes -keyout \

        client-key.pem -out client-req.pem

        Generating a 2048 bit RSA private key

        ………………………………………………………………………………………+++

        …+++

        writing new private key to ‘client-key.pem’


        You are about to be asked to enter information that will be incorporated

        into your certificate request.

        What you are about to enter is what is called a Distinguished Name or a DN.

        There are quite a few fields but you can leave some blank

        For some fields there will be a default value,

        If you enter ‘.’, the field will be left blank.


        Country Name (2 letter code) [GB]:CN

        State or Province Name (full name) [Berkshire]:Beijing

        Locality Name (eg, city) [Newbury]:Beijing

        Organization Name (eg, company) [My Company Ltd]:CH

        Organizational Unit Name (eg, section) []:

        Common Name (eg, your name or your server’s hostname) []:mysqlclient

        Email Address []:

        Please enter the following ‘extra’ attributes

        to be sent with your certificate request

        A challenge password []:abc123

        An optional company name []:


        shell>openssl rsa -in client-key.pem -out client-key.pem 

        //移除client-key中的passphrase[可选]

        writing RSA key


        shell>openssl x509 -req -in client-req.pem -days 3600 -CA ca-cert.pem \

        -CAkey ca-key.pem -set_serial 01 -out client-cert.pem 

        //签署客户端证书

        Signature ok

        subject=/C=CN/ST=Hangzhou/L=Hangzhou/O=CH/CN=mysqlclient

        Getting CA Private Key


    5. 生成完毕后,验证步骤如下

        shell>openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem

        server-cert.pem: OK

        client-cert.pem: OK


    6. 综上步骤,生成如下文件:

        ca-cert.pem  在服务器端和客户端都是用 ssl-ca=ca-cert.pem

        server-cert.pem,server-key.pem 服务器端指定 ssl-cert=server-cert.pem 和 \

        ssl-key=server-key.pem

        client-cert.pem,client-key.pem 客户端指定 ssl-cert=client-cert.pem 和 \

        ssl-key=client-key.pem

三、配置SSL连接

    实现使用SSL进行配置和赋权的两种方案


    1. 方案1

        Server:

            1)在服务器端的配置文件my.cnf中添加如下参数:

                [mysqld]

                ssl-cert=/db/ssl/server-cert.pem

                ssl-key=/db/ssl/server-key.pem

            2)重启mysqld。


        用户赋权,用GRANT语句的REQUIRE SSL选项

            mysql>create user ​​user@localhost​​ identified by ‘abc’;

            mysql>grant select on testdb.* to ​​user@localhost​​ require ssl;

        

        Client:

            mysql -u user -pabc -P 3300 ssl-ca=ca-cert.pem


    2. 方案2

        Server:

            1)在服务器端的配置文件my.cnf中添加如下参数:

                [mysqld]

                ssl-ca=/db/ssl/ca-cert.pem

                ssl-cert=/db/ssl/server-cert.pem

                ssl-key=/db/ssl/server-key.pem

            2)重启mysqld。


        用户赋权,用GRANT语句的REQUIRE x509选项

            mysql>create user ​​user@localhost​​ identified by ‘abc’;

            mysql>grant select on testdb.* to ​​user@localhost​​ require x509;


        Client:

            mysql -u user -pabc -P 3300 ssl-ca=ca-cert.pem ssl-key=client-key.pem \

            ssl-cert=client-cert.pem


    注意:方案2的验证要求更严格,需要指定key和cert,因此推荐使用方案2。


四、检查

    1. 配置完成后,可以如下方式查看自身对ssl的支持:

        mysql> show global variables like ‘%ssl%’; #查看服务器是否支持SSL连接

        +---------------+-------------------------+

        | Variable_name | Value                   |

        +---------------+-------------------------+

        | have_openssl  | YES                     |

        | have_ssl      | YES                     |

        | ssl_ca        | /db/ssl/ca-cert.pem     |

        | ssl_capath    |                         |

        | ssl_cert      | /db/ssl/server-cert.pem |

        | ssl_cipher    |                         |

        | ssl_key       | /db/ssl/server-key.pem  |

        +---------------+-------------------------+


        mysql> SHOW STATUS LIKE ‘Ssl_cipher’; #查看本连接是否是SSL加密的连接

        +---------------+--------------------+

        | Variable_name | Value              |

        +---------------+--------------------+

        | Ssl_cipher    | DHE-RSA-AES256-SHA |

        +---------------+--------------------+


    1. 通过抓包工具,相同的select * from t1命令,可以明显看到加密前后包信息的不同。

        1)加密前:

          

        2)加密后:

          

------------------------------------------------------------------------------------------

附:SSL协议的工作方式简介

客户端要收发几个握手信号:

发送一个“ClientHello”消息,说明它支持的密码算法列表、压缩方法及最高协议版本,也发送稍后将被使用的随机数。

然后收到一个“ServerHello”消息,包含服务器选择的连接参数,源自客户端初期所提供的“ClientHello”。

当双方知道了连接参数,客户端与服务器交换证书(依靠被选择的公钥系统)。这些证书通常基于X.509,不过已有草案支持以OpenPGP为基础的证书。

服务器请求客户端公钥。客户端有证书即双向身份认证,没证书时随机生成公钥。

客户端与服务器通过公钥保密协商共同的主私钥(双方随机协商),这通过精心谨慎设计的伪随机数功能实现。结果可能使用Diffie-Hellman交换,或简化的公钥加密,双方各自用私钥解密。所有其他关键数据的加密均使用这个“主密钥”。