新特性解读 | 从 wireshark 看 MySQL 8.0 加密连接

作者:秦福朗
爱可生 DBA 团队成员,负责项目日常问题处理及公司平台问题排查。热爱 IT,喜欢在互联网里畅游,擅长摄影、厨艺,不会厨艺的 DBA 不是好司机,didi~
本文来源:原创投稿
*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
引言
社区之前的文章“快速掌握 MySQL 8.0 认证插件的使用”中说道,MySQL 8.0 使用 caching_sha2_password 认证插件进行加密连接,初步介绍了加密连接,本文从网络抓包层面看一下在使用 caching_sha2_password 插件的 MySQL 8.0 是如何进行加密连接的。
一、MySQL 5.7 未加密连接的情况
环境:
MySQL 5.7.25
tcpdump 4.9.2
wireshark 3.2.2
1.1 抓包
tcpdump -i eth0 -s 0 host 10.186.65.69 and port 3306 -w ./5.7.cap
1.2 MySQL 通过 tcp 进行连接,并执行测试 SQL
shell> mysql -uroot -pxxxx -h10.186.60.73 -P3306
mysql> show databases;
mysql> select * from qinfulang.sbtest1 limit 1;
mysql> exit
1.3 通过 wireshark 解析抓包

从上图可以分析以下信息:

从包 9-20 可以看出,没有使用加密连接插件的情况下,在经过抓包工具抓包后,经过 wireshark 就可以直接解析到查询语句,非常不安全。
Tips:
此处提供一个小技巧: 在 wireshark 里,编辑-首选项-Protocols-MySQL 里可以设置是否在解析窗口的 info 列里面显示 SQL query 语句以及可以设置 MySQL TCP 默认端口。

二、MySQL 8.0 加密连接
环境:
MySQL 8.0.15
tcpdump 4.9.2
wireshark 3.2.2
2.1 抓包
tcpdump -i eth0 -s 0 host 10.186.65.69 and port 3306 -w ./8.0.cap
2.2 MySQL 通过 tcp 进行连接,并执行测试 SQL
shell> mysql_8.0 -uroot -pxxxx -h10.186.60.73 -P3306
mysql> show databases;
mysql> select * from qinfulang.sbtest1 limit 1;
mysql> exit
这里在测试 SQL 之外查看一下 status
mysql> status
--------------
./mysql Ver 8.0.15 for linux-glibc2.12 on x86_64 (MySQL Community Server - GPL)
Current user: root@10.186.65.69
SSL: Cipher in use is DHE-RSA-AES128-GCM-SHA256
Server version: 8.0.15 MySQL Community Server - GPL
Protocol version: 10
Connection: 10.186.60.73 via TCP/IP
TCP port: 3306
可以这里使用的算法为 DHE-RSA-AES128-GCM-SHA256
2.3 通过 wireshark 解析抓包

从上图可以分析以下信息:

2.4 分析使用 TLS 加密连接握手过程
首先,这里为什么是 TLS 而不是 SSL?
TLS 为传输层安全性协议,是 MySQL 在客户端与服务器之间进行加密连接的协议。TLS 有时被称为 SSL(安全套接层),但是 MySQL 实际上并不使用 SSL 协议进行加密连接,因为它的加密很弱。TLS 协议通过加密数据来确保在两个通信应用程序之间提供隐私和数据完整性,以便任何第三方都无法拦截通信。它还会验证对等方以验证其身份。通过在两个对等点之间提供安全的通信通道,TLS 协议可以保护消息的完整性并确保其不会被篡改。
MySQL 支持多种 TLS 版本协议,此次测试使用 8.0 的 client 为 TLSv1.2。
从 wireshark 中看一下 TLS 握手的步骤:

分步解析:
包 8:从客户端到服务端进行 ClientHello,进行问候通信,来启动整个握手环节。

此处包含:TLS 协议版本号,32 字节的随机数,用于计算 Master secret 及创建加密密钥,客户端用于标识会话的唯一编号 Session ID 以及客户端支持的密码套件列表,打开密码套件列表 Cipher Suites 就能看到 MySQL 8.0 使用的 DHE-RSA-AES128-GCM-SHA256 算法。
包 10:服务器返回的 ServerHello。进行问候返回,

此处包含:服务器版本号,服务器的 32 字节随机数,用于生成 Master secret,用来标识与客户端的 Session ID,服务器和客户端都支持的密码套件,此处为 MySQL 8.0 使用的 DHE-RSA-AES128-GCM-SHA256 算法,还有压缩方式,可选,此处为 null。
包 11:
Certificate:服务器向客户端发送 x.509 证书列表对客户端身份进行验证,证书内包含公钥。

Server Key Exchange:服务器密钥交换,这里发送服务器使用的 DH 参数。

Certificate Request:客户证书申请,此处是服务器希望对客户端进行身份验证发送的信息,包含了所需要的证书类型。

Server Hello Done:服务器打招呼结束,等待客户端返回信息。

包 13:
Certificate:客户端证书。

Client Key Exchange:客户端密钥交换。

此处包含:服务器验证客户端协议版本与原始的 client hello 的消息是否匹配,由客户端生成使用服务端公钥加密的随机数 Pre-master secret 以进行服务器对客户端的身份验证。
Change Cipher Spec:客户端通知服务器,所有未来的消息都使用刚刚协商的算法与密钥进行加密传输。

Encrypted Handshake Message:完成 TLS 消息加密,此处数据已使用刚刚协商的密钥与算法进行了加密。

包 14:
New Session Ticket:新的会话标签,记录了加密参数。

Change Cipher Spec:服务器通知客户机,将使用现有的算法和密钥对信息进行加密。

Encrypted Handshake Message:完成 TLS 消息加密,客户端成功解密并验证了信息,服务器就成功通过了身份验证。

到此 TLS 消息加密握手过程结束,后面 Application Date 即为加密后的数据流。
写在最后
MySQL 8.0 的加密插件在使用中兼顾了安全与性能,建议使用默认开启,在 MySQL 8.0.16 后支持 TLSv1.3 协议。
目前网络上尝试过对 TLS 解密的手法,经笔者测试均不能在 wireshark 上解密 MySQL 8.0 的 TLS 加密消息。如果有新手法,可留言交流。
如果要进行一些 wireshark 对 MySQL 抓包的测试,需要看到 SQL query,目前建议采用 MySQL 5.7 版本或在 MySQL 8.0 上 skip-ssl 关闭加密通信。