暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Public Key Retrieval is not allowed 问题记录

原创 HoldOnBash 2023-06-09
3211
  • 背景

因其他变更需要重启数据库,随后业务启动发现异常。

  • 环境版本

MySQL8.0.15

  • 现象

业务报障:Public Key Retrieval is not allowed

报错截图:

0

  • 原因分析

此时在数据库查看业务账号连接状态皆为"Receiving from client" 状态

排查方向一、ssl检查

网上的答案很多都是修改代码配置项:

解决此异常问题需要将allowPublicKeyRetrieval=true和useSSL=false。

但是我这边只是重启了数据库,业务侧并没有任何的改动。因此不应该从修改代码配置这里解决问题。

查看ssl参数是启用的

0

排查方向二、检查身份认证插件

0

  • 问题根因
  1. 这套数据库不是标准化安装的,所以在8.0环境中默认使用了caching_sha2_password插件(标准化场景中默认插件沿用5.7的mysql_native_password
  2. 数据库重启后,业务账号没有登录缓存。在禁用SSL/TLS协议传输且当前用户在服务器端没有登录缓存的情况下,客户端没有办法拿到服务器的公钥,出现上面的报错。

出现该问题的时候,MySQL配置的密码认证插件为如下两种:

  • sha256_password
  • caching_sha2_password

值得注意的是,如果使用“mysql_native_password”密码认证插件,不会出现“Public Key Retrieval is not allowed”错误。

首先MySQL 8.0默认推荐使用“sha256_password”和“caching_sha2_password”这两种认证插件。只有较老的MySQL版本仍然会使用“mysql_native_password”。

“Public Key Retrieval is not allowed”错误产生的原因

首先MySQL 8.0默认推荐使用“sha256_password”和“caching_sha2_password”这两种认证插件。只有较老的MySQL版本仍然会使用“mysql_native_password”。

根据MySQL提供的官方文档(https://dev.mysql.com/doc/refman/8.0/en/caching-sha2-pluggable-authentication.html),这两种插件都是使用SHA256算法来对密码进行保护。这些插件的具体执行流程如下:

  1. 检查客户端是否禁用SSL/TLS加密传输;
  2. 如果客户端未禁用SSL/TLS加密传输,则客户端在进行认证时的认证报文(传输用户名和密码的报文)是使用TLS进行传输的,两种插件认为认证报文传输安全,不进行任何其他操作;
  3. 如果客户端禁用SSL/TLS加密传输,则客户端在进行认证时的认证报文(传输用户名和密码的报文)是使用明文进行传输的,两种插件认为认证报文传输不安全,会单独对明文报文中的密码使用RSA加密方式进行加密。

SSL/TLS认证流程

  • 启用SSL/TLS加密传输的客户端认证流程

如上述流程所述,当客户端未禁用SSL/TLS加密传输时,通过Wireshark等抓包工具可以观察到整个客户端与MySQL服务端交互的过程都被TLS协议加密保护了。

虽然会产生登录的明文报文,但是该明文报文中的用户信息为空,真正的用户信息在TLS握手阶段后的密文中。如下图所示:

0

  • 禁用SSL/TLS加密传输的客户端认证流程

如上述流程所述,当客户端禁用SSL/TLS加密传输时(比如JDBC连接串设置useSSL=false参数),用户的登录信息会在明文中进行传输

明文传输密码存在安全问题,此时,两种插件会尝试使用RSA加密(RSA encryption)方法对明文报文中的密码部分进行加密,加密后的密码部分如下图所示:

0

根据前面的分析,导致“Public Key Retrieval is not allowed”主要是由于当禁用SSL/TLS协议传输后,客户端会使用服务器的公钥进行传输,默认情况下客户端不会主动去找服务器拿公钥,此时就会出现上述错误。

经过查阅官方文档,出现Public Key Retrieval的场景可以概括为在禁用SSL/TLS协议传输且当前用户在服务器端没有登录缓存的情况下,客户端没有办法拿到服务器的公钥。具体的场景如下:

  1. 新建数据库用户,首次登录;
  2. 数据库的用户名、密码发生改变后登录;
  3. 服务器端调用FLUSH PRIVELEGES指令刷新服务器缓存。

针对上述错误,有如下的解决方案:

一、使用“sha256_password”和“caching_sha2_password”这两种认证插件时,代码侧需要改动

  1. 在条件允许的情况下,不要禁用SSL/TLS协议,即不要在CLI客户端使用--ssl-mode=disabled,或在JDBC连接串中加入useSSL=false;
  2. 如果必须禁用SSL/TLS协议,则可以尝试使用CLI客户端登录一次MySQL数据库制造登录缓存;
  3. 如果必须禁用SSL/TLS协议,则可以通过增加如下参数允许客户端获得服务器的公钥:
  • 在JDBC连接串中加入allowPublicKeyRetrieval=true参数;
  • 在CLI客户端连接时加入--get-server-public-key参数;
  • 在CLI客户端连接时加入--server-public-key-path=file_name参数,指定存放在本地的公钥文件。

二、使用mysql_native_password插件,数据库侧需要改动

  1. 修改有问题的用户密码,使用旧版的mysql_native_password插件。
  2. 设置默认认证插件为旧版的mysql_native_password插件。

本次问题的解决办法

  1. 卸载了密码插件validate_password。
  2. 创建了新的业务账号做替换,使用了旧版的mysql_native_password插件。

上面部分内容是网络摘抄的,如有侵权联系我删除即可


「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论