作者:胡呈清

爱可生 DBA 团队成员,善于故障剖析、性能优化,集体博客:https://www.jianshu.com/u/a95...,欢送探讨。

本文起源:原创投稿

*爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。


TLS or SSL ?

SSL(Secure Socket Layer 安全套接层)是基于 HTTPS 下的一个协定加密层,最后是由网景公司(Netscape)研发,后被 IETF(The Internet Engineering Task Force - 互联网工程工作组)标准化后写入(RFCRequest For Comments 申请正文),RFC 里蕴含了很多互联网技术的标准。

起初是因为HTTP在传输数据时应用的是明文(尽管说 POST 提交的数据时放在报体里看不到的,然而还是能够通过抓包工具窃取到)是不平安的,为了解决这一隐患网景公司推出了SSL安全套接字协定层,SSL 是基于 HTTP 之下 TCP 之上的一个协定层,基于 HTTP 规范并对 TCP 传输数据时进行加密,所以 HTTPS 是 HTTP+SSL/TCP的简称。

因为 HTTPS 的推出受到了很多人的欢送,在 SSL 更新到 3.0 时,IETF 对 SSL3.0 进行了标准化,并增加了多数机制(然而简直和 SSL3.0无差别),标准化后的 IETF 更名为 TLS1.0(Transport Layer Security 平安传输层协定),能够说 TLS 就是 SSL 的新版本 3.1 。

TLS(Transport Layer Security)是更为平安的升级版 SSL。但 SSL 这一术语更为罕用,实际上 MySQL 应用的就是 TLS 协定,而不是 SSL 协定。

1. TLS 握手过程

想弄清楚上面这一大堆文件的作用是什么吗?那就必须先理解 TLS 握手过程

├── ca-key.pem├── ca.pem├── client-cert.pem├── client-key.pem├── server-cert.pem└── server-key.pem

1.1 TLS 握手过程

TLS 握手的过程,其实就是秘钥替换的过程,这也是整个TLS 加密技术里最简单的一个环节,参考一张网上的图如下:

1.2 密钥算法

对称密钥算法:数据加密和解密时应用雷同的密钥。

非对称密钥算法:数据加密和解密时应用不同的密钥,一个是公开的公钥,一个是由用户机密保留的私钥。利用公钥(或私钥)加密的数据只能用相应的私钥(或公钥)能力解密。

与非对称密钥算法相比,对称密钥算法具备计算速度快的长处,通常用于对大量信息进行加密(如对所有报文加密);而非对称密钥算法,个别用于数字签名和对较少的信息进行加密。

留神:SSL/TLS 协定就是应用对称密钥算法进行数据加密,应用非对称密钥算法进行”对称密钥“的加密。其过程为:

  1. 上图中,Server端发送了公钥给客户端,私钥本人保留,这是非对称密钥算法中的公钥、私钥对;
  2. 客户端会创立一个密钥,这个就是对称加密算法中的密钥。而后用 Server 端的公钥对这个密钥加密,发送给 Server 端;
  3. Server 端收到客户端发送过去的加密过的密钥,应用本人的私钥进行解密,失去加密前的密钥;
  4. 接下来传输数据则应用“对称密钥”进加密和解密。

这个就是利用非对称密钥算法保障对称密钥自身的平安。

1.3 数字证书-如何保障公钥的真实性?

如果有攻击者伪造了 Server 端的公钥并发了客户端,客户端会拜访到假网站被窃取信息。显然保障客户端收到的 Server 端的公钥是实在的,是保障整个加密连贯可靠性的第一道防线。

数字证书由权威机构 CA(Certification Authority) 签发,签发过程为:

  1. 用户首先产生本人的密钥对,并将公钥及局部个人身份信息传送给 CA ;
  2. CA 核实用户身份(将执行一些必要的步骤,以确信申请的确由用户发送而来);
  3. CA 对用户的所有信息(公钥、所有者、有效期...)进行 Hash 计算,失去一个 Hash 值,而后再应用私钥对 Hash 值进行加密失去签名,就失去了数字证书。该证书蕴含:用户的公钥、所有者、有效期等信息,同时还附有CA的签名信息。

数字证书的验证流程:

  1. 客户端会应用同样的 Hash 算法获取该数字证书的 Hash 值 H1;
  2. 通常浏览器和操作系统中集成了 CA 证书(蕴含 CA 公钥、所有者),客户端获得这个CA证书,应用其中的 CA 公钥解密签名,失去一个 Hash 值 H2 ;
  3. 比拟 H1 和 H2,如果值雷同,则数字证书可信。

上述签发和验证流程见下图(参考自网络):

如果 CA 证书不在浏览器和操作系统的可信赖区,这种 CA 证书通常被称为自签名 CA 证书(MySQL 主动生成的就是自签名证书,详见下文)。要实现数字证书的验证,则必须当时将自签名 CA 证书放到客户端,并在客户端发动连贯时指定这个 CA 证书文件;或者当时将自签名 CA 证书导入到客户端的操作系统可信赖区,这样在 TLS 握手过程中也能主动获取到这个 CA 证书。

另外:验证证书在 SSL/TLS 协定中不肯定是必须的,比方 mysql 客户端只有指定 --ssl-mode=VERIFY_CA 或者 --ssl-mode=VERIFY_IDENTITY 时才验证 CA 证书。如果 --ssl-mode=REQUIRED,则不验证 CA 证书,只要求 MySQL Server 端发送公钥给客户端,这就无奈保障服务端公钥是实在属于 MySQL server 的。具体见下文。

2. MySQL SSL 加密连贯

2.1 MySQL服务端的配置

启动参数:

  • --ssl:示意 MySQL 服务端容许加密连贯,这个启动参数MySQL8.0默认启用

零碎变量:

  • require_secure_transport:指定是否要求客户端应用加密连贯。默认值为 OFF,如果 ON,则示意客户端必须应用加密连贯,如果客户端敞开 ssl ,则连贯会报错。

以下参数指定加密连贯时应用的证书和密钥文件:

ssl_ca=ca.pemssl_cert=server-cert.pemssl_key=server-key.pem

MySQL8.0 在启动时会主动生成 SSL 证书、密钥文件,以及 RSA 密钥对文件;或者应用 mysql_ssl_rsa_setup 程序生成上述文件。也能够手工生成:

## SSL证书和密钥文件certs├── ca-key.pem├── ca.pem├── client-cert.pem├── client-key.pem├── server-cert.pem└── server-key.pem# Create CA certificate# 创立CA证书(蕴含CA公钥)和CA私钥openssl genrsa 2048 > ca-key.pemopenssl req -new -x509 -nodes -days 3600 \        -key ca-key.pem -out ca.pem# Create server certificate, remove passphrase, and sign it# server-cert.pem = public key, server-key.pem = private key# 学生成服务器公钥、私钥# 应用CA私钥对服务器公钥签名,失去服务器证书 server-cert.pem,证书中蕴含公钥、所有者、有效期等明文信息,也有通过 CA 私钥加密对公钥、所有者、有效期...加密后的签名openssl req -newkey rsa:2048 -days 3600 \        -nodes -keyout server-key.pem -out server-req.pemopenssl rsa -in server-key.pem -out server-key.pemopenssl x509 -req -in server-req.pem -days 3600 \        -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem# Create client certificate, remove passphrase, and sign it# client-cert.pem = public key, client-key.pem = private key# 学生成客户端公钥、私钥# 应用CA私钥对客户端公钥签名,失去客户端证书 client-cert.pem,个别不须要验证客户端身份,这些文件就不须要用到。当然如果要同时验证 MySQL Server 身份和客户端身份,就须要用到这些文件了。openssl req -newkey rsa:2048 -days 3600 \        -nodes -keyout client-key.pem -out client-req.pemopenssl rsa -in client-key.pem -out client-key.pemopenssl x509 -req -in client-req.pem -days 3600 \        -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem# 查看证书内容openssl x509 -text -in ca.pem# 验证CA证书(“应用CA证书验证数字证书”更失当?)openssl verify -CAfile ca.pem server-cert.pem# 输入后果:server-cert.pem: OK

2.2 MySQL客户端配置

MySQL 客户端连贯 Server 时,通过 --ssl-mode 参数指定:

  • --ssl-mode=PREFFERED,默认行为,client 端尝试应用加密进行连贯,如果无奈构建加密连贯,则会退回到未加密的连贯
  • --ssl-mode=REQUIRED时,Client 端须要加密连贯,如果无奈构建连贯,则 Client 端将失败
  • --ssl-mode=DISABLED,Client 端应用未加密的连贯
  • --ssl-mode=VERIFY_CA,Client 端须要加密连贯,并且还对 CA 证书进行验证
  • --ssl-mode=VERIFY_IDENTITY,Client 端须要加密的连贯,并且还针对 CA 证书和其证书中的服务器主机名执行验证

留神:主机名身份验证 VERIFY_IDENTITY 不适用于由服务器主动创立或应用 mysql_ssl_rsa_setup 手动创立的自签名CA证书。

测试如下:

##当指定 --ssl-mode=REQUIRED,仅要求加密连贯,不须要验证 MySQL Server 身份,所以会间接信赖 MySQL Server 发送给客户端的公钥(即 server-cert.pem 数字证书中的明文公钥,疏忽其中的数字签名信息)[root@172-16-21-5 /]# /opt/mysql/base/8.0.21/bin/mysql -h172.16.21.4 -P3306 -utest -ptestpass --ssl-mode=REQUIRED -e "select 1"mysql: [Warning] Using a password on the command line interface can be insecure.+---+| 1 |+---+| 1 |+---+##当指定 --ssl-mode=VERIFY_CA,须要验证 CA 证书,因为这个 CA 证书是自签发的,所以不在浏览器和操作系统的可信赖区,无奈从浏览器和操作系统的可信赖区这个公共渠道获取 CA 证书,所以报错:[root@172-16-21-5 /]# /opt/mysql/base/8.0.21/bin/mysql -h172.16.21.4 -P3306 -utest -ptestpass --ssl-mode=VERIFY_CAERROR 2026 (HY000): SSL connection error: CA certificate is required if ssl-mode is VERIFY_CA or VERIFY_IDENTITY##将MySQL服务端的 ca.pem 拷贝到客户端scp ca.pem 172.16.21.5:/tmp/##--ssl-mode=VERIFY_CA,指定须要验证 CA 证书,因为这个 CA 证书是自签发的,所以不在浏览器和操作系统的可信赖区,则必须要将 CA 证书拷贝到客户端,并指定 CA 证书文件##TLS 握手过程中,MySQL Server 发送服务器数字证书 server-cert.pem 给客户端,客户端应用 CA 证书中的 CA 公钥解密 server-cert.pem 中的签名,验证通过,才能够失常登陆:[root@localhost ~]# mysql -h10.186.61.173 -P3308 -uhucq -p'1qaz@WSX' \--ssl-ca="/tmp/ca.pem" \--ssl-mode=VERIFY_CA \-e "select 1"+---+| 1 |+---+| 1 |+---+##因为MySQL主动生成的CA证书是自签名证书,而 --ssl-mode=VERIFY_IDENTITY 不适用于由服务器主动创立或应用 mysql_ssl_rsa_setup手动创立的自签名CA证书,即便指定本地的CA证书文件,连贯也会失败[root@localhost ~]# mysql -h10.186.61.173 -P3308 -uhucq -p'1qaz@WSX' \--ssl-ca="/tmp/ca.pem" \--ssl-mode=VERIFY_IDENTITY \-e "select 1"ERROR 2026 (HY000): SSL connection error: Failed to verify the server certificate via X509 certificate matching functions

2.3 MySQL SSL 连贯中的 TLS 握手过程

上述示例已有具体阐明,这里再简要总结一下:

  1. 客户端发动 ssl 连贯申请;
  2. MySQL Server 发送数字证书 server-cert.pem 给客户端(server-cert.pem蕴含:服务器公钥、CA签名信息);
  3. 客户端应用CA 证书 ca.pem(因为这是 MySQL 自签名的CA证书,无奈从操作系统的可信赖区获取(压根不在这里边),所以当时必须在客户端本地保留 CA 证书文件)中的 CA 公钥解密 server-cert.pem 中的签名,进行验证;
  4. 验证通过后,生成对称密钥,应用 server-cert.pem 中的公钥加密“对称密钥”,发送给 MySQL Server;
  5. MySQL Server 应用本人保留的私钥 server-key.pem 解密,失去“对称密钥”;
  6. 接下来传输数据则应用“对称密钥”进加密和解密。

如果仅指定 --ssl-mode=REQUIRED,不指定 --ssl-mode=VERIFY_CA 或者 --ssl-mode=VERIFY_IDENTITY,则不须要步骤3。

3. JDBC 如何设置SSL连贯

首先 MySQL Server 端必须生成 SSL 证书和密钥文件,并且在启动时指定启动参数:--ssl(个别将其写到 my.cnf 中)。MySQL8.0 启动时会主动生成SSL 证书和密钥文件,并默认应用 --ssl 参数。

JDBC 敞开 ssl 连贯示例:jdbc:mysql://localhost:3306/hucq?useSSL=false

如果 MySQL Server 应用 caching_sha2_password(MySQL8.0默认的认证插件)、sha256_password 认证插件,则还必须指定 AllowPublicKeyRetrieval=True,因为 caching_sha2_password 插件要求替换明码时必须应用 RSA 公钥加密(在没有应用SSL加密连贯的状况下),AllowPublicKeyRetrieval=True 参数作用是申请 MySQL Server 端发送 RSA 公钥给客户端,如果不申请 RSA 公钥并且又没有指定客户端本地RSA公钥文件(先从 MySQL 服务器上拷贝 RSA 公钥到本地),则连贯会报错。应该配置:jdbc:mysql://localhost:3306/hucq?useSSL=false&AllowPublicKeyRetrieval=True

JDBC 开启 SSL 连贯,意味着要求平安连贯,则应该开启 CA 证书认证,跟 mysql 客户端一样,须要将 MySQL 的自签名 CA 证书导入到客户端,或者放到 ftp 上,再通过 JDBC 参数指定 CA 证书门路,比较复杂,请参考官网文档:https://dev.mysql.com/doc/con...

参考资料

  1. https://tangyuxian.com/2021/0...
  2. https://dev.mysql.com/doc/ref...