共计 6677 个字符,预计需要花费 17 分钟才能阅读完成。
作者:胡呈清
爱可生 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 协定就是应用对称密钥算法进行数据加密,应用非对称密钥算法进行”对称密钥“的加密。其过程为:
- 上图中,Server 端发送了公钥给客户端,私钥本人保留,这是非对称密钥算法中的公钥、私钥对;
- 客户端会创立一个密钥,这个就是对称加密算法中的密钥。而后用 Server 端的公钥对这个密钥加密,发送给 Server 端;
- Server 端收到客户端发送过去的加密过的密钥,应用本人的私钥进行解密,失去加密前的密钥;
- 接下来传输数据则应用“对称密钥”进加密和解密。
这个就是利用非对称密钥算法保障对称密钥自身的平安。
1.3 数字证书 - 如何保障公钥的真实性?
如果有攻击者伪造了 Server 端的公钥并发了客户端,客户端会拜访到假网站被窃取信息。显然保障客户端收到的 Server 端的公钥是实在的,是保障整个加密连贯可靠性的第一道防线。
数字证书由权威机构 CA(Certification Authority) 签发,签发过程为:
- 用户首先产生本人的密钥对,并将公钥及局部个人身份信息传送给 CA;
- CA 核实用户身份(将执行一些必要的步骤,以确信申请的确由用户发送而来);
- CA 对用户的所有信息(公钥、所有者、有效期 …)进行 Hash 计算,失去一个 Hash 值,而后再应用私钥对 Hash 值进行加密失去签名,就失去了数字证书。该证书蕴含:用户的公钥、所有者、有效期等信息,同时还附有 CA 的签名信息。
数字证书的验证流程:
- 客户端会应用同样的 Hash 算法获取该数字证书的 Hash 值 H1;
- 通常浏览器和操作系统中集成了 CA 证书(蕴含 CA 公钥、所有者),客户端获得这个 CA 证书,应用其中的 CA 公钥解密签名,失去一个 Hash 值 H2;
- 比拟 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.pem
ssl_cert=server-cert.pem
ssl_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.pem
openssl 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.pem
openssl rsa -in server-key.pem -out server-key.pem
openssl 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.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl 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_CA
ERROR 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 握手过程
上述示例已有具体阐明,这里再简要总结一下:
- 客户端发动 ssl 连贯申请;
- MySQL Server 发送数字证书 server-cert.pem 给客户端(server-cert.pem 蕴含:服务器公钥、CA 签名信息);
- 客户端应用 CA 证书 ca.pem(因为这是 MySQL 自签名的 CA 证书,无奈从操作系统的可信赖区获取(压根不在这里边),所以当时必须在客户端本地保留 CA 证书文件)中的 CA 公钥解密 server-cert.pem 中的签名,进行验证;
- 验证通过后,生成对称密钥,应用 server-cert.pem 中的公钥加密“对称密钥”,发送给 MySQL Server;
- MySQL Server 应用本人保留的私钥 server-key.pem 解密,失去“对称密钥”;
- 接下来传输数据则应用“对称密钥”进加密和解密。
如果仅指定 –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…
参考资料
- https://tangyuxian.com/2021/0…
- https://dev.mysql.com/doc/ref…